驱动程序类如何位于JDBC4中

JDBC版本4中的一个重要补充您不必再通过调用Class.forName显式加载驱动程序。 当您的应用程序第一次尝试连接数据库时, DriverManager自动加载应用程序CLASSPATH的驱动程序。

我的问题是怎么样? 如果类路径中有多个驱动程序怎么办?

我可以猜到的一件事是,在解析连接URL时,是否需要驱动程序是JDBC或ODBC,但是如何从多个jdbc兼容的驱动程序中说出哪一个将被选择用于我正在使用的数据库? (假设我使用的是MySql,我需要MySql-Connector驱动程序)。 在JVM中是否存在此类数据库驱动程序的静态映射?

有关JDBC4驱动程序加载的一些信息来自: http ://www.onjava.com/2006/08/02/jjdbc-4-enhancements-in-java-se-6.html

当调用getConnection方法时,DriverManager将尝试从初始化时加载的JDBC驱动程序中找到合适的驱动程序,并使用与当前应用程序相同的类加载器显式加载。

DriverManager方法getConnection和getDrivers已得到增强,可支持Java SE服务提供程序机制(SPM)。 根据SPM,服务被定义为一组众所周知的接口和抽象类,服务提供者是服务的特定实现。 它还指定服务提供者配置文件存储在META-INF / services目录中。 JDBC 4.0驱动程序必须包含文件META-INF / services / java.sql.Driver。 此文件包含JDBC驱动程序的java.sql.Driver实现的名称。 例如,要加载JDBC驱动程序以连接到Apache Derby数据库,META-INF / services / java.sql.Driver文件将包含以下条目:

 org.apache.derby.jdbc.EmbeddedDriver 

现在回答你的问题。

我的问题是怎么样? 如果类路径中有多个驱动程序怎么办?

作为类加载器规则,将首先加载任何找到的类,如果它已经加载,则不会被类加载器重新加载。

每个符合JDBC 4的驱动程序在其jar中都有一个名为META-INF/services/java.sql.Driver文件,在该文件中它将列出其java.sql.Driver 。 当您请求连接时, DriverManager将使用ServiceLoader在类路径中查找META-INF/services/java.sql.Driver所有(!)副本,然后加载列出的所有类。 当加载java.sql.Driver类时,它必须使用DriverManager注册自己,因此DriverManager使用服务加载器加载所有类,并且每个Driver实现注册自己。

当您从DriverManager请求连接时, DriverManager将遍历所有已注册的驱动程序,要求它们进行Connection 。 驱动程序将使用JDBC url检查它是否支持它的协议(例如,Jaybird / Firebird JDBC检查url是否以"jdbc:firebirdsql:""jdbc:firebird:"开头)。 如果驱动程序不支持协议,它将返回null ,如果它支持协议,它将返回已建立的连接,或者它将抛出SQLException (例如,如果您在URL中出错,或者它不能连接)。 如果所有驱动程序都返回null (none支持协议),那么DriverManager将抛出一个SQLException ,错误"No suitable driver found for "

因此,只要它们支持不同的协议,在类路径上有多个驱动程序并不重要,但是如果同一数据库有多个驱动程序(或至少:相同的协议前缀),它将使用驱动程序列表中的第一个驱动程序,并且如果该驱动程序因SQLException失败,则不会尝试另一个。

在JDBC 4中,驱动程序会自动注册。 怎么会这样? 我们写的时候

 Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/sonoo","root","root"); 

这将调用DriverManager类中的静态块。 如果打开DriverManager源文件,则可以看到静态块

  static { loadInitialDrivers(); println("JDBC DriverManager initialized"); } 

这将调用函数loadInitialDrivers(); function和加载所有驱动程序并自动注册。 所以我们不需要显式注册或加载驱动程序。