为什么要使用class.forname在DriverManager.getConnection之前
JDBC在getConnection之前为什么要调用Class.forName 获取一个数据库连接的通用模板如下:
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会自动去加载合适的驱动。
为什么要使用class.forname在DriverManager.getConnection之前的更多相关文章
- OAF_JDBC系列2 - 通过JDBC连接SQLSERVER数据库DriverManager.getConnection
d try{ Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); St ...
- Eclipse中利用JSP把mysql-connector-java-8.0.13.jar放到WebContent\WEB-INF\lib中连接MySQL数据库时Connection conn = DriverManager.getConnection(url,username,password)报错的解决办法
开发环境: 1.系统:windows 7/8/10均可 2.jdk:1.8.0_144 3.服务器:apache-tomcat-9.0.8 4.IDE:eclipse+jsp 0.网页代码如下: &l ...
- JDBC中的DriverManager.getConnection(url)中的参数url
1.Oracle8/8i/9i数据库(thin模式) Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); ...
- jdbc的数据库驱动类DriverManager.getConnection()详解
1.Oracle8/8i/9i数据库(thin模式) Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); ...
- Connection conn = DriverManager.getConnection("jdbc:odbc:bbs");
Connection conn = DriverManager.getConnection("jdbc:odbc:bbs"); 这是JDBC连接数据库的时候用的一句话,,Conne ...
- JDBC详解系列(三)之建立连接(DriverManager.getConnection)
在JDBC详解系列(一)之流程中,我将数据库的连接分解成了六个步骤. JDBC流程: 第一步:加载Driver类,注册数据库驱动: 第二步:通过DriverManager,使用url,用户名和密码 ...
- SparkCore | Rdd| 广播变量和累加器
Spark中三大数据结构:RDD: 广播变量: 分布式只读共享变量: 累加器:分布式只写共享变量: 线程和进程之间 1.RDD中的函数传递 自己定义一些RDD的操作,那么此时需要主要的是,初始化工作 ...
- Spring Data 起步
[Maven 坐标]G A V ……………………………………………………………………………………………………………………………………………… [JDBC] Connection 连接数据库 State ...
- 【大数据】SparkCore学习笔记
第1章 RDD概述 1.1 什么是RDD RDD(Resilient Distributed Dataset)叫做分布式数据集,是Spark中最基本的数据抽象.代码中是一个抽象类,它代表一个不可变.可 ...
随机推荐
- MyEclipse10安装SVN插件
一.下载SVN插件subclipse 下载地址:http://subclipse.tigris.org/servlets/ProjectDocumentList?folderID=2240 在打开的网 ...
- 去掉iPhone、iPad的默认按钮样式 去掉高光样式:
input[type="button"], input[type="submit"], input[type="reset"] { -web ...
- git使用相关文章的链接
http://search.fishc.com/cse/search?s=14988791857133860392&q=git&partner=discuz http://bbs.fi ...
- css 去除 a,checkbox 框 出现虚线
在开发过程中遇到checkbox框,第一次遇到还以为是系统自带的是这样 后来发现不是那样, 我们可以在使用css 去掉出现的虚线框,以下是我的解决方案代码: /* checkbox 去掉虚框*/:fo ...
- MVC 基架不支持 Entity Framework 6 或更高版本
MVC 基架不支持 Entity Framework 6 或更高版本.有关详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=276833. PS:新做一个 ...
- yii的csv导出
数据导出,简单的csv导出, public static function export($parameter){ if (is_array($parameter)) { $filename = da ...
- HDU2203 亲和串
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- 拼装query的sql语句
com.kingdee.bos.metadata.query.util.QuerySqlAccessBase //打开一个绑定query界面,获取query查询的最终sql,231行
- Mac 配置 vim
Mac 配置 vim 安装 vim 7.4 cd ~ hg clone https://code.google.com/p/vim/ cd vim ./configure --with-feature ...
- python中%和format
两者都是格式化字符串用的,前者是比较老的版本,现在已经不推荐,后者更强大一些 % In [22]: print '%s' % 'hello world' hello world In [23]: pr ...