作者:踏山321 | 来源:互联网 | 2023-08-31 19:30
Oneofthegreatadditionsinversion4ofJDBCYoudonthavetoexplicitlyloadthedriverbycall
One of the great additions in version 4 of JDBC You don't have to explicitly load the driver by calling Class.forName
anymore. When your application attempts to connect the database for the first time, DriverManager
automatically loads the driver found in the application CLASSPATH
.
在JDBC的第4版中,您不必通过调用类显式地加载驱动程序。forName了。当应用程序第一次尝试连接数据库时,DriverManager会自动加载在应用程序类路径中找到的驱动程序。
My question is how? What if there are multiple drivers in the classpath?
我的问题是如何?如果类路径中有多个驱动程序怎么办?
One thing I can guess is that on parsing the connection URL whether driver needed is of JDBC or ODBC can be figured out but how can one say out of multiple jdbc compliant drivers which one is to be selected for the database I am using? (lets say I am using MySql and I need MySql-Connector driver). Is there any static mapping of such database drivers in JVM?
我能猜到的一件事是,在解析连接URL时,是否需要JDBC驱动程序或ODBC驱动程序,是可以算出来的,但是如何从多个兼容JDBC的驱动程序中选择一个驱动程序,用于我正在使用的数据库呢?(假设我正在使用MySql,我需要sql - connector driver)。JVM中有这种数据库驱动程序的静态映射吗?
3 个解决方案
10
Every JDBC 4 compliant driver has a file in its jar called META-INF/services/java.sql.Driver
, in that file it will list its implementation(s) of java.sql.Driver
. When you request a connection, DriverManager
will use the ServiceLoader
to find all(!) copies of META-INF/services/java.sql.Driver
in the classpath and will then load all classes listed. When a java.sql.Driver
class is loaded, it has to register itself with the DriverManager
, so the DriverManager
loads all classes using the service loader, and each Driver
implementation registers itself.
每个兼容JDBC 4的驱动程序在其jar中都有一个名为META-INF/services/java.sql的文件。在该文件中,它将列出java.sql.Driver的实现。当您请求一个连接时,DriverManager将使用ServiceLoader来找到META-INF/services/java.sql的所有(!)副本。驱动程序在类路径中,然后将加载列出的所有类。当一个java.sql。驱动程序类被加载,它必须向驱动程序管理器注册自己,因此驱动程序管理器使用服务加载器加载所有类,每个驱动程序实现注册自己。
When you request a connection from DriverManager
, the DriverManager
will iterate over all registered drivers asking them for a Connection
. The driver will use the JDBC url to check if its a protocol it supports (eg Jaybird/Firebird JDBC checks if the url starts with "jdbc:firebirdsql:"
or "jdbc:firebird:"
). If the driver does not support the protocol, it will return null
, if it does support the protocol it will either return an established connection, or it will throw an SQLException
(eg if you made an error in the URL, or it couldn't connect). If all drivers return null
(none support the protocol), then DriverManager
will throw an SQLException
with error "No suitable driver found for "
当您从驱动管理器请求连接时,驱动管理器将遍历所有请求连接的已注册驱动程序。驱动程序将使用JDBC url检查它是否支持它的协议(例如Jaybird/Firebird JDBC检查url是否以“JDBC:firebirdsql:”或“JDBC: Firebird:”开头)。如果驱动程序不支持协议,它将返回null,如果它支持协议,它将返回一个已建立的连接,或者它将抛出一个SQLException(例如,如果URL出错,或者它无法连接)。如果所有的驱动程序都返回null(不支持该协议),那么DriverManager将会抛出一个带有错误的SQLException,“不适合在
中找到合适的驱动程序”。
So having multiple drivers on the classpath does not matter as long as they support different protocols, however if there are multiple drivers for the same database (or at least: same protocol prefixes), it will use the first in the list of drivers, and if that driver fails with an SQLException
, it will not try the other one.
所以有多个驱动程序类路径无关紧要,只要他们支持不同协议,但是如果有多个驱动程序相同的数据库(或者至少:协议前缀相同),它将使用列表中的第一个司机,如果司机没有抛出SQLException,它不会尝试另一个。