研究JDBC架构下,如何与数据库协调工作(以MySQL为例)
JDBC如何连接数据库
只需要Class.forName一句话即可完成Mysql数据库驱动加载。
(jdk1.6以后,无需这句话即可加载驱动,jdbc通过SPI机制完成机制,后面会简单介绍)
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(...)
JDBC(SQL)类图
JDBC加载数据库驱动的时序图
获取数据库连接的时序图
分析
JDBC让用户能够利用类加载(Class.forName), 一句话来完成数据库的记载,同时通过java.sql.Driver和java.sql.Connection规定的数据库和连接的行为。理解了JDBC的实现方式,有利于我们自己的程序架构的设计。
SPI(Service Provider Interface)
- @since 1.6
ServiceLoader
从jdk1.6引入的ServiceLoader, 可以自动完成实现了指定Inteface的类的加载。DriverManager利用了该设计,从而让jdk1.6以后的数据库驱动加载完全自动化。用户代码只需要DriverMananger.getConnection就可以得到数据库连接。
关键代码如下:
java.sql.DriverManager
/*
* Load the initial JDBC drivers by checking the System property
* jdbc.drivers and then use the {@code ServiceLoader} mechanism
*/
private static void ensureDriversInitialized() {
...
// If the driver is packaged as a Service Provider, load it.
// Get all the drivers through the classloader
// exposed as a java.sql.Driver.class service.
// ServiceLoader.load() replaces the sun.misc.Providers()
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();
/* Load these drivers, so that they can be instantiated.
* It may be the case that the driver class may not be there
* i.e. there may be a packaged driver with the service class
* as implementation of java.sql.Driver but the actual class
* may be missing. In that case a java.util.ServiceConfigurationError
* will be thrown at runtime by the VM trying to locate
* and load the service.
*
* Adding a try catch block to catch those runtime errors
* if driver not available in classpath but it's
* packaged as service and that service is there in classpath.
*/
try {
while (driversIterator.hasNext()) {
driversIterator.next(); // 会加载实现了java.sql.Driver的MySQL的类,从而完成数据库驱动的安装
}
} catch (Throwable t) {
// Do nothing
}
return null;
}
});
SPI的java.sql.Driver服务接口的全限定类名:
mysql-connector-java-5.1.49.jar\META-INF\services\java.sql.Driver
文件内容
com.mysql.jdbc.Driver
com.mysql.fabric.jdbc.FabricMySQLDriver
因此,上述两个类会自动加载,实现数据库驱动的安装。