JDBC版本4中的一个重要补充您不必显式加载
司机再打电话给Class.forName
。当您的应用程序首次尝试连接数据库时,DriverManager
会自动加载找到的驱动程序
应用程序CLASSPATH
。
我的问题是怎么回事?如果类路径中有多个驱动程序怎么办?
我可以猜到的一点是,在解析连接URL时,是否需要驱动程序是JDBC或ODBC,但是如何从多个jdbc兼容的驱动程序中说出要为我正在使用的数据库选择一个驱动程序? (假设我使用的是MySql,我需要MySql-Connector驱动程序)。 JVM中是否存在此类数据库驱动程序的静态映射?
答案 0 :(得分:13)
每个符合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
(没有人支持协议),那么DriverManager
会抛出SQLException
错误"No suitable driver found for <url>"
因此,在类路径上有多个驱动程序并不重要,只要它们支持不同的协议,但是如果同一个数据库有多个驱动程序(或至少:相同的协议前缀),它将使用列表中的第一个司机根据Java版本,如果该驱动程序失败并显示SQLException
,它将继续使用下一个驱动程序(至少Java 5及更高版本),或者停止尝试并抛出异常(我相信这是在Java 1.4或甚至可能更早。)
答案 1 :(得分:11)
有关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 /服务/ java.sql.Driver中。该文件包含的名称 JDBC驱动程序的java.sql.Driver实现。例如,要加载 用于连接Apache Derby数据库的JDBC驱动程序 META-INF / services / java.sql.Driver文件将包含以下内容 项:
org.apache.derby.jdbc.EmbeddedDriver
现在回答你的问题。
我的问题是怎么样?如果有多个驱动程序怎么办? 类路径?
作为类加载器规则,将首先加载任何找到的类,如果它已经加载,则不会被类加载器重新加载。
答案 2 :(得分:0)
在JDBC 4中,驱动程序会自动注册。怎么会这样? 我们写的时候
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/sonoo","root","root");
这将调用DriverManager
类中的静态块。如果打开DriverManager源文件,则可以看到静态块
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
这将调用函数loadInitialDrivers();
函数并加载所有驱动程序并自动注册。因此,我们不需要明确注册或加载驱动程序。
答案 3 :(得分:0)
您的问题的答案将从java.sql.DriverManager Java类中获取,方法为loadInitialDrivers。
drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty("jdbc.drivers");
}
});
如果程序找到多个jdbc驱动程序,它将使用以下逻辑获取确切的驱动程序
String[] driversList = drivers.split(":");
println("number of Drivers:" + driversList.length);
for (String aDriver : driversList) {
try {
println("DriverManager.Initialize: loading " + aDriver);
Class.forName(aDriver, true,
ClassLoader.getSystemClassLoader());
} catch (Exception ex) {
println("DriverManager.Initialize: load failed: " + ex);
}