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会自动去加载合适的驱动。
http://www.ticmy.com/?p=249

时间: 2024-10-13 08:00:10

JDBC在getConnection之前为什么要调用Class.forName(转)的相关文章

JDBC对MySQL数据库存储过程的调用

一.MySQL数据库存储过程: 1.什么是存储过程 存储过程(英文:Stored Procedure)是在大型数据库系统中,为了完毕特定功能而编写的一组的SQL语句集.存储过程经编译存储在数据库中.用户通过指定存储过程的名字并给出參数(假设该存储过程带有參数)来运行它. 2.与一般SQL语句相比.使用存储过程有哪些长处.有哪些缺点 长处: 1).降低了脚本的运行环节,缩短了获取数据的时间.存储过程仅仅在创建的时进行编译,在调用使用的时候直接运行.不需再次编译:而一般SQL语句每次运行前都须要编译

JDBC学习2:为什么要写Class.forName("XXX")?

Class.forName(String name) 接上一篇JDBC.本来这个内容是放在前面的一篇里面的一起的,后来发现越写越多,想想看就算了,还是单独开一篇文章好了,这样也能写得更加详细点. 上一篇文章的第4点,getConnection()方法里面,我把从.properties里面获取mysqlpackage的地方替换成实际的 value值,那么替换后的应该是Class.forName("com.mysql.jdbc.Driver"),实际上所有的JDBC连接先写的基本 上也都是

jdbc的相关知识

如何通过jdbc访问数据库? java数据库连接(java Database Connectivity,jdbc)是一种用于实现java程序中数据库操作功能.它提供了执行sql语句,访问各种数据库的方法,并为个各种不同的数据库提供了相同的操作接口.java.sql中包含了所有数据库操作的类.通过jdbc操作数据库主要有以下几步: (1)加载驱动器,将数据库的驱动加载到classpath中,在基于javaee的web开发中,一般将数据库驱动拷贝到WEB-INF/lib下. (2)加载驱动,将数据库

Class.forName和registerDriver的区别

我们都知道JDBC的代码怎么写,比如以MySQL JDBC为例 //注册JDBC驱动 Class.forName("com.mysql.jdbc.Driver"); //然后就可以拿到JDB的连接 DriverManager.getConnection("jdbc:mysql://localhost/quickstart", "root", "!123456"); 通过阅读MySQL JDBC的 源代码,本文将讲述这两段代码背

在Jena框架下基于MySQL数据库实现本体的存取操作

在Jena框架下基于MySQL数据库实现本体的存取操作 转自:http://blog.csdn.net/jtz_mpp/article/details/6224311 最近在做一个基于本体的管理系统.其中对本体的操作部分,我使用的是Jena框架:数据模型是基于本体的语义模型:数据存储则是MySQL 5.5.9版本.由此看来,将本体模型存入数据库和从数据库中取出模型是常用的操作,这里总结一下我学到的方法. 我使用的开发环境是Eclipse3.6,在开发前要将必要的与jena有关的类包加入java

新人项目遇到的问题

一:mysql服务无法启动 方案:修改 my-default的basedir和datadir; mysqld -install mysqld -initialize mysql -u root -p 二:忘记密码,修改时报错 方案:将passowrd改为authentication_String 三:添加DBdriver时报错,说是url报错 方案:将默认的改为com.mysql.jdbc.Driver 四:jsp中调用class.forName("com.mysql.jdbc.Driver&q

JDBC存储过程的调用

一. JDBC存储过程的调用 (1)存储过程是用SQL语句和控制流语句等编写的一段程序代码,在创建时已被编译成机器代码并存储在数据库中供客户端调用. 存储过程有以下优点: 1.所生成的机器代码被永久存储在数据库中,客户端调用时不需要重新编译,执行起来效率要高一些. 2.存储过程的网络使用效率比等效的SQL 语句要高. (2)JDBC通过java.sql.CallableStatement接口调用数据库服务器中的存储过程: (3)CallableStatement接口继承了PreparedStat

Java——JDBC小结

---恢复内容开始--- 1.首先说明什么是JDBC在第一眼看到这个名词之前,我觉得有必要知道它的英文全称是什么,Java Database Connectivity,从英文字面上理解就直译为可连通的Java数据库,说白了也就是想提供一套中间环节,去连接Java代码与数据库,使之可以直接通过操作Java代码就可以控制数据库. 2.JDBC的实质它是Java访问数据库的解决方案,希望能过用同样的方式访问不同的数据库,以达到实现与具体数据库无关的Java操作界面.JDBC实质上就是就是一套标准化的接

利用JDBC连接Oracle数据库(转)

http://blog.csdn.net/wahaha1_/article/details/8512438 JDBC是Sun公司制定的一个可以用Java语言连接数据库的技术. 一.JDBC基础知识 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成.JDBC为数据库开发人员提供了一个标准的API,据此可以构建更高级的工具和接口,使数据库开发人员