`

Class.forName与DriverManager区别

 
阅读更多
在学习JDBC的时候,通常有两种方式去注册数据库驱动程序(这里采用MySQL数据库),分别为:
Java代码 
DriverManager.registerDriver(new Driver()); 
Class.forName("com.mysql.jdbc.Driver"); 
那么这两种方式有什么异同呢?首先我们到DriverManager中去看一下,
Java代码 
   public static synchronized void registerDriver(java.sql.Driver driver) 
throws SQLException { 
if (!initialized) { 
    initialize(); 

      
DriverInfo di = new DriverInfo(); 
 
di.driver = driver; 
di.driverClass = driver.getClass(); 
di.driverClassName = di.driverClass.getName(); 
 
// Not Required -- drivers.addElement(di); 
 
writeDrivers.addElement(di);  
println("registerDriver: " + di); 
 
/* update the read copy of drivers vector */ 
readDrivers = (java.util.Vector) writeDrivers.clone(); 
 
   } 
      很明显,DriverManager将我们需要注册的驱动程序信息封装成DriverInfo放进了一个writeDrivers中,这个writeDrivers是DriverManager中声明的一个static类型Vector变量。在getConnection的时候会再用到。
       那么Class.forName("com.mysql.jdbc.Driver")是如何注册驱动程序的呢,我们知道Class.forName("类名")的主要作用是向虚拟机实例化一个Class实例,我们看一下com.mysql.jdbc.Driver的源代码。
Java代码 
public class Driver extends NonRegisteringDriver implements java.sql.Driver { 
    // ~ Static fields/initializers 
    // --------------------------------------------- 
 
    // 
    // Register ourselves with the DriverManager 
    // 
    static { 
        try { 
            java.sql.DriverManager.registerDriver(new Driver()); 
        } catch (SQLException E) { 
            throw new RuntimeException("Can't register driver!"); 
        } 
    } 
        在 com.mysql.jdbc.Driver中有一段静态代码块,是向 DriverManager注册一个Driver实例。这样在 Class.forName("com.mysql.jdbc.Driver")的时候,就会首先去执行这个静态代码块,于是和DriverManager.registerDriver(new Driver())有了相同的效果。
         那么对于这两种方法,在这里,我推荐使用第二种,即Class.forName("类名")的方式。原因有两点
1、在我们执行DriverManager.registerDriver(new Driver())的时候,静态代码块也已经执行了,相当于是实例化了两个Driver对象。
2、 DriverManager.registerDriver(new Driver())产生了一种对MySQL的一种依赖。而Class.forName的方式我们完全可以在运行的时候再动态改变。



所有JDBC的书都跟我们说使用Class.forName可以强制装载jdbc Driver,但从来没有人告诉我们是如何实现的。这一说法最早应该由think in java给出,而这一点一直让我疑惑。

Class.forName用于将class装载入内存,建立一个相应的class类实例,然后返回句柄。如果不用这个方法来明确建立class类实例,而直接用new来建立实际的类实例,则在建立实例前仍然会用classloader来得到class实例(如果内存中没有),然后再建立类实例,因此用getClass方法可以得到class实例。

我们知道在建立实例时,会调用其构建函数,这称为初始化,这一步骤包括对其属性的初始化。但是如果不建立实例,而建立相应的class类实例,就象Class.forName所作的那样,又会做哪些工作呢?对于那些静态变量(属性)的初始化将在该阶段完成,这也就是为什么在不建立实例的时候就可以调用静态变量的原因。另外一些静态代码,即static{}中的代码也将在这里执行。

最初我认为自动注册的代码由jvm完成,它将检测装载的类,如果实现driver接口,就直接调用DriverManager.registerDriver(new Driver())来完成注册,但是这显然与classloader本身需要完成的工作无关,那么由DriverManager来完成检测吗?这就需要一个专门用于检测的线程,显然会影响jvm的性能。因此另一个实现方案就是使用静态代码,则在driver的实现类中必然有如下代码static{DriverManager.registerDriver(new Driver());},该代码在装载class文件建立class类时自动执行完成注册。

那么事实究竟如何呢?根据我们的推测,如果使用DriverManager.registerDriver(new Driver())来显式注册,则实际上会注册两次,一次是在装载class类时由代码static{DriverManager.registerDriver(new Driver());}来完成,一次则是执行我们写的DriverManager.registerDriver(new Driver())代码。

这是用DriverManager.registerDriver(new JdbcOdbcDriver())来显式注册时,用DriverManager.getDrivers()得到的注册的drivers,

sun.jdbc.odbc.JdbcOdbcDriver@42e816

sun.jdbc.odbc.JdbcOdbcDriver@9304b1

显然sun.jdbc.odbc.JdbcOdbcDriver被注册了两次。

因此在注册driver时,用Class.forName是最好的方法,它保证了DriverManager中的driver的唯一性。DriverManager.registerDriver(new JdbcOdbcDriver())虽然不会产生代码错误,但显然会影响执行效率,因为在依次查询driver时,多个相同的driver的存在显然会导致查询量的增加。


分享到:
评论

相关推荐

    浅析使用JDBC操作MySQL需要添加Class.forName(“com.mysql.jdbc.Driver”)

    如果熟悉使用JDBC来连接数据库的同学一定很清楚连接数据库的代码中一定会有依据Class.forName (com.mysql.jdbc.Driver); public static Connection getConnection() throws ClassNotFoundException, SQLException ...

    jdbc驱动程序实例

    Class.forName("org.gjt.mm.mysql.Driver").newInstance(); //或者Class.forName("com.mysql.jdbc.Driver"); String url ="jdbc:mysql://localhost/myDB? user=soft&password=soft1234&useUnicode=true&...

    java于各种数据库连接额语句

    Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb"; //mydb为数据库 String user="sa"; String password=...

    java连接数据库字符串

    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); //Sql Server7.0/2000数据库 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); //DB2数据库 Class....

    jdbc笔记整理 sql

    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); //Sql Server7.0/2000 数据库 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); //DB2 数据库 Class.froName(...

    JDBC连接各种数据代码.doc

    Class.forName( "oracle.jdbc.driver.OracleDriver" ); con = DriverManager.getConnection( "jdbc:oracle:thin:@127.0.0.1:1521:ORCL", "scott", ”tiger”); 连接SqlServer2000 msbase.jar ...

    MySQL 5.7版本以上数据库的连接驱动jar包

    这是MySQL 5.7版本以上数据库的连接驱动jar包,对应加载驱动程序代码: Class.forName("com.mysql.cj.jdbc.Driver"); 该驱动包适用于Java web开发,连接MySQL数据库时导入工程。 参考代码: Class.forName(...

    mysql57驱动jar包

    这是MySQL 5.7版本以上数据库的连接驱动jar包,对应加载驱动程序代码: Class.forName("com.mysql.cj.jdbc.Driver"); 该驱动包适用于Java web开发,连接MySQL数据库时导入工程。 参考代码: Class.forName(...

    mysql 5.7 57版本以上数据库驱动 jar

    这是MySQL 5.7版本以上数据库的连接驱动jar包(解压密码1234),对应加载驱动程序代码: Class.forName("com.mysql.cj.jdbc.Driver"); 该驱动包适用于Java web开发,连接MySQL数据库时导入工程。 参考代码: Class....

    Webtest(jsp).rar_Java ODBC SQLSERVER_http/2-class.com/_jsp_试卷_选择

    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") String driver = "jdbc:odbc:try" Connection conn = DriverManager.getConnection(driver,"sa","") //如果是windows验证,则不用用户名和密码

    sql2008_jdbc

    压缩包里有个jar包,压缩包中有使用说明。 sqljdbc4.jar 适合 JDK6.0 及以上的;

    Java 连接多种数据库代码参考

    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID String user="test"; String password="test"; Connection conn...

    常用数据库jdbc连接写法大全

     class.forname( "org.gjt.mm.mysql.driver" );  cn = drivermanager.getconnection( "jdbc:mysql://mydbcomputernameorip:3306/mydatabasename", susr, spwd );    2. postgresql(http://www.de.postgresql.org...

    sql jdbc 2.0.1607.1 UNIX

    Therefore, applications do not need to call the Class.forName method to register or load the driver when using the sqljdbc4.jar class library. When the getConnection method of the DriverManager ...

    java 连接 DB 总汇合

    3. Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); 4. 5. String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID 6. 7. String user="test"; 8. 9. String ...

    sql jdbc 2.0

    Therefore, applications do not need to call the Class.forName method to register or load the driver when using the sqljdbc4.jar class library. When the getConnection method of the DriverManager ...

    JDBC Driver

     Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" );  cn = DriverManager.getConnection( "jdbc:microsoft:sqlserver://MyDbComputerNameOrIP:1433;DatabaseName=master", sUsr, sPwd ); //...

Global site tag (gtag.js) - Google Analytics