驱动程序类如何位于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和加载所有驱动程序并自动注册。 所以我们不需要显式注册或加载驱动程序。