博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JDBC在getConnection之前为什么要调用Class.forName
阅读量:2171 次
发布时间:2019-05-01

本文共 3140 字,大约阅读时间需要 10 分钟。

http://www.ticmy.com/?p=249

获取一个数据库连接的通用模板如下:

String driver =
"oracle.jdbc.OracleDriver"
;
String url =
"jdbc:oracle:thin:@127.0.0.1:1521:orcl"
;
String user =
"scott"
;
String password =
"ticmy"
;
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, user, password);

里面有个Class.forName(driver),这句话有什么作用?将驱动类load到内存?如果没有这句会怎么样?运行发现,如果去掉这一句会有以下异常:

java.sql.SQLException: No suitable driver found for xxx….

在解释具体原因之前先简单看下Class.forName做了什么。

假设一个类以前从来没有被装进内存过,Class.forName(String className)这个方法会做以下几件事情:
1、装载。将字节码读入内存,并产生一个与之对应的java.lang.Class类对象
2、连接。这一步会验证字节码,为static变量分配内存,并赋默认值(0或null),并可选的解析符号引用(这里不理解没关系)
3、初始化。为类的static变量赋初始值,假如有static int a = 1;这个将a赋值为1的操作就是这个时候做的。除此之外,还要调用类的static块。(这一步是要点)

Class.forName(String className)方法会将这三步都做掉,如下面的例子:

package
com.ticmy.oracle;
 
public
class
TestClinit {
    
public
static
void
main(String[] args)
throws
Exception {
        
Class.forName(
"com.ticmy.oracle.ABC"
);
    
}
}
class
ABC {
    
private
static
int
a = getNum();
    
static
{
        
System.out.println(
"this is static block"
);
    
}
    
public
static
int
getNum() {
        
System.out.println(
"getNum"
);
        
return
1
;
    
}
}

程序的运行结果是:

getNum
this is static block

那么,Class.forName(driver)这个driver类里有没有什么static块呢?去探究一下。例子用的是Oracle,反编译下oracle.jdbc.OracleDriver,发现其继承了oracle.jdbc.driver.OracleDriver,那么继续看这个oracle.jdbc.driver.OracleDriver,确实有个static块,里面有这样的代码:

static
{
    
Timestamp localTimestamp = Timestamp.valueOf(
"2000-01-01 00:00:00.0"
);
    
try
{
      
if
(defaultDriver ==
null
) {
        
defaultDriver =
new
OracleDriver();
        
DriverManager.registerDriver(defaultDriver);
      
}
    
}
catch
(RuntimeException localRuntimeException) {
    
}
catch
(SQLException localSQLException){}
    
_Copyright_2004_Oracle_All_Rights_Reserved_ =
null
;
}

再看看mysql吧:com.mysql.jdbc.Driver:

同样发现了static块,里面代码如下:

static
{
    
try
{
      
DriverManager.registerDriver(
new
Driver());
    
}
catch
(SQLException E) {
      
throw
new
RuntimeException(
"Can't register driver!"
);
    
}
}

再看一个db2:com.ibm.db2.jcc.DB2Driver:

也发现了static块:

static
{
    
if
(o.Nb !=
null
) {
      
exceptionsOnLoadDriver__ = dg.a(o.Nb, exceptionsOnLoadDriver__);
    
}
 
    
try
{
      
registeredDriver__ =
new
DB2Driver();
      
DriverManager.registerDriver(registeredDriver__);
    
}
    
catch
(SQLException localSQLException) {
      
exceptionsOnLoadDriver__ =
new
SqlException(
null
,
      
"Error occurred while trying to register Jcc driver with JDBC 1 Driver Manager"
);
      
exceptionsOnLoadDriver__.setNextException(localSQLException);
    
}
}

无一例外地,发现里面都有DriverManager.registerDriver(driver)的调用。那么是不是可以将开头的例子中的Class.forName换成DriverManager.registerDriver呢?

String url =
"jdbc:oracle:thin:@127.0.0.1:1521:orcl"
;
String user =
"scott"
;
String password =
"ticmy"
;
DriverManager.registerDriver(
new
OracleDriver());
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
conn.close();

经过测试发现OK。现在,已经知道Class.forName(driver)的根本目的就是为了调用DriverManager.registerDriver

Class.forName还有个重载的方法:Class.forName(String name, boolean initialize, ClassLoader loader),Class.forName(String className)就等价于Class.forName(className, true, currentLoader),注意中间的参数为true,这个参数的含义就是要不要初始化。如果此参数为true且指定的类以前没有被初始化过,就会去初始化。

另外,jdbc4已经不需要显式的调用Class.forName了,在jdbc4中,调用getConnection的时候DriverManager会自动去加载合适的驱动。

转载地址:http://tbqzb.baihongyu.com/

你可能感兴趣的文章
FFmpeg 命令操作音视频
查看>>
问题:Opencv(3.1.0/3.4)找不到 /opencv2/gpu/gpu.hpp 问题
查看>>
目的:使用CUDA环境变量CUDA_VISIBLE_DEVICES来限定CUDA程序所能使用的GPU设备
查看>>
问题:Mysql中字段类型为text的值, java使用selectByExample查询为null
查看>>
程序员--学习之路--技巧
查看>>
解决问题之 MySQL慢查询日志设置
查看>>
contOS6 部署 lnmp、FTP、composer、ThinkPHP5、docker详细步骤
查看>>
TP5.1模板布局中遇到的坑,配置完不生效解决办法
查看>>
PHPstudy中遇到的坑No input file specified,以及传到linux环境下遇到的坑,模板文件不存在
查看>>
TP5.1事务操作和TP5事务回滚操作多表
查看>>
composer install或composer update 或 composer require phpoffice/phpexcel 失败解决办法
查看>>
TP5.1项目从windows的Apache服务迁移到linux的Nginx服务需要注意几点。
查看>>
win10安装软件 打开时报错 找不到 msvcp120.dll
查看>>
PHPunit+Xdebug代码覆盖率以及遇到的问题汇总
查看>>
PHPUnit安装及使用
查看>>
PHP项目用xhprof性能分析(安装及应用实例)
查看>>
composer安装YII
查看>>
Sublime text3快捷键演示
查看>>
sublime text3 快捷键修改
查看>>
关于PHP几点建议
查看>>