驱动程序类如何位于JDBC4中

时间:2013-08-17 11:04:15

标签: java database jdbc

JDBC版本4中的一个重要补充您不必显式加载 司机再打电话给Class.forName。当您的应用程序首次尝试连接数据库时,DriverManager会自动加载找到的驱动程序 应用程序CLASSPATH

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

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

4 个答案:

答案 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);
        }