本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载自夜明的孤行灯
本文链接地址: 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
的属性,同时getConnection
和getDrivers
方法都会调用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/