加载驱动程序和注册驱动程序之间的区别

7

我对JDBC非常陌生,所以我写了一个小程序来检查已注册的驱动程序。我想要做到以下几点:

  1. 在没有加载任何驱动程序的情况下检查注册的数量:

    我本来以为它会什么都不显示,但惊讶地发现它显示了3个已注册的驱动程序。

  2. 使用Class.forName()加载一个驱动程序:

    我本来期望它会再次显示四个驱动程序,但惊讶地发现它只显示了3个驱动程序。

  3. 最后,使用DriverManager注册驱动程序

    现在它显示了四个驱动程序。

请问有谁可以帮助我理解这里发生了什么。我的问题如下:

  1. 这三个驱动程序是默认加载/注册的吗?
  2. 使用Class.forName加载类不会自动注册驱动程序吗?(从我的经验来看,我猜答案是否定的,但我想确认一下)如果不是,那么加载类只是寻找接口的实现,例如(DriverManager等)吗?
  3. 最后,加载驱动和注册驱动之间有什么区别?

我列出了程序和输出供您参考。

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import oracle.jdbc.driver.OracleDriver;

class Test3{
 public static void main(String[] args) throws Exception{

     //checking for registered drivers
     System.out.println("Drivers registered initially");
     Enumeration enumm = DriverManager.getDrivers();
     int count=1;
     while(enumm.hasMoreElements()){
         Driver dr=(Driver)enumm.nextElement();
         System.out.println(count+" "+dr);
         count++;
     }

     //loading the driver
     Class.forName("oracle.jdbc.driver.OracleDriver");
     System.out.println("\n\nDrivers after class loading");
     enumm = DriverManager.getDrivers();
     count=1;
     while(enumm.hasMoreElements()){
         Driver dr=(Driver)enumm.nextElement();
         System.out.println(count+" "+dr);
         count++;
     }

     //After Registering driver
     OracleDriver odr= new OracleDriver();
     DriverManager.registerDriver(odr);
     System.out.println("\nAfter registering oracle driver");
     enumm = DriverManager.getDrivers();
     count=1;
     while(enumm.hasMoreElements()){
         Driver dr=(Driver)enumm.nextElement();
         System.out.println(count+" "+dr);
         count++;
     }

}
}

输出:

Drivers registered initially

1 sun.jdbc.odbc.JdbcOdbcDriver@2c84d9

2 oracle.jdbc.OracleDriver@8bdcd2

3 com.mysql.jdbc.Driver@1f31ad9

这些是数据库驱动程序的名称和版本号。在Java编程中使用这些驱动程序,可以帮助连接不同类型的数据库。
Drivers after class loading

1 sun.jdbc.odbc.JdbcOdbcDriver@2c84d9

2 oracle.jdbc.OracleDriver@8bdcd2

3 com.mysql.jdbc.Driver@1f31ad9

这些是不同的数据库驱动程序。每个驱动程序都有一个唯一标识符,以便在连接到数据库时进行识别和使用。

After registering oracle driver

1 sun.jdbc.odbc.JdbcOdbcDriver@2c84d9

2 oracle.jdbc.OracleDriver@8bdcd2

3 com.mysql.jdbc.Driver@1f31ad9

4 oracle.jdbc.driver.OracleDriver@167acf2

这是四个不同数据库所使用的驱动程序名称和ID。

你使用哪个JDK? - Florescent Ticker
2个回答

4
JDBC规范要求符合条件的驱动程序在加载时(使用静态初始化块)向java.sql.DriverManager注册自己。您不应该自己注册驱动程序。
从JDBC 4.0(Java 6)开始,JDBC驱动程序需要指定服务定义,声明驱动程序提供的所有java.sql.Driver实现(通常为一个)。这是通过文件META-INF/services/java.sql.Driver完成的。 DriverManager将在类路径上查询此文件的所有实例(使用{{link1:java.util.ServiceLoader}}),并加载这些文件中包含的所有驱动程序实现。由于(符合条件的)驱动程序需要注册自己,因此现在所有这些实现都已向DriverManager注册。
因此:
  1. 现在加载驱动程序不再需要使用 Class.forName(...);(除非驱动程序不符合 JDBC 4 标准)
  2. 您不应该手动向 DriverManager 注册驱动程序(除非驱动程序不符合 JDBC 1 标准,或者特别构建为不注册自己)

在您的具体代码中,您有三个符合 JDBC 4 标准的驱动程序(至少与服务定义相关),因此它们会自动加载。执行 Class.forName(..) 没有任何效果,因为类已经被加载(因此不会再次加载)。当您手动注册驱动程序时(如我之前所说,您应该永远不要这样做),它将向已注册的驱动程序列表中添加一个额外的实例。


"JDBC 1 兼容" - Yousha Aleayoub
1
@YoushaAleayoub 驱动程序需要在第一个JDBC规范中向DriverManager进行注册,因此符合“JDBC 1兼容性”。 - Mark Rotteveel

2

从JDK6开始,如果JVM在类路径中发现任何驱动程序类,则JDBC驱动程序将自动加载。在JDK6中不需要使用Class.forName语句。这就是为什么您可以得到驱动程序,因为它们在您的类路径中并由JVM加载。


我正在使用Jdk-7.. 我忘记提到了。 - User27854
这仅适用于 JDBC 4 兼容驱动程序,它们在其 jar 中具有所需的服务定义(因此旧驱动程序或不兼容的驱动程序不会自动加载)。 - Mark Rotteveel
我的意思是该功能在JDK6中添加,因此在JDK7中肯定是相同的.. 在这里检查链接http://docs.oracle.com/cd/E13157_01/wlevs/docs30/jdbc_drivers/usedriver.html - Naveen Ramawat
请在此链接中阅读有关JDBC 4.0功能的内容:http://www.onjava.com/pub/a/onjava/2006/08/02/jjdbc-4-enhancements-in-java-se-6.html - Naveen Ramawat
我一定会仔细阅读它。谢谢。 - User27854
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接