JDBC驱动加载和Class.forName

23 3月

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载自夜明的孤行灯

本文链接地址: https://www.huangyunkun.com/2014/03/23/jdbc-with-class-forname/

我很少直接使用原生的JDBC,更多是使用mybatis或者hibernate。

上周需要用一用,就到网上Copy了一段代码,一切运行正常。但是有一句话有点奇怪

Class.forName("com.mysql.jdbc.Driver")

这句话我原来也用过,一直是以为这是加载对应驱动用的,直到我删除了它,我才发现好像它不是必须的。那这东西是干嘛的?

虽然网上的很多代码片段是抄来抄去的,但是我觉得这样写一定是有原因。

Class.forName

实现看看这句话本身的用处。

在Java世界中,类只有在被使用的时候才本加载,更准确的是说在你寻求类的相关信息的时候才加载。

比如有一个类名为SomeOne

publicclass SomeOne {

}

然后在一个调用它的类名为SomeOneCaller

publicclass SomeOneCaller {
publicstatic SomeOne someOne =null;
publicstatic Class<?> someOne = SomeOne.class;
}

第一句话并没有导致类的加载,而第二句话触发了加载。

而Class.forName语句是加载对应名称的类,这里的加载是指读取了字节码,并执行static代码块。

也就是在使用JDBC时调用这句话可以保证我们在执行DriverManager的getConnection
方法时它已经被载入JVM中了。

也就是说Class.forName本身和JDBC没有什么关系,它所做的只是加载对应名称的类。

JDBC

JDBC是一套标准API,用于数据库连接和SQL语句执行等等。
既然是标准,那么一定是有相关规范的。

要在getConnection时调用正确的类,一般的JDBC驱动都会调用registerDriver方法注册自己。

比如在Mysql的驱动中:

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

这是一个static代码块,也是使用Class.forName的一个理由。由Class.forName加载类,
进而完成加载。

但是在后来的JDBC标准中(JDBC 4.0)规定,DriverManager会读取名为jdbc.drivers的属性,同时getConnectiongetDrivers方法都会调用Service Provider去获取信息。

而这些内容包含在META-INT/services目录中,如postgresql-jdbc中的内容为:

org.postgresql.Driver

也就是说只要你的JDBC驱动包含了这个信息,那么就完全不需要使用Class.forName语句了。

什么时候需要使用Class.forName

在某些情况下还是需要使用Class.forName来先行就在JDBC驱动,不过这些都属于一些特定情况:

  • Java 6 以下版本

  • 版本较老的JDBC驱动

基本上就现在使用JDBC已经不需要使用Class.forName了。

结语

说来十分惭愧,这么古旧的一个问题居然我现在才知道。

大部分相关讨论都是若干年前的…

参考资料

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载自夜明的孤行灯

本文链接地址: https://www.huangyunkun.com/2014/03/23/jdbc-with-class-forname/

发表评论

您的电子邮箱地址不会被公开。