mysql drivermanager_jdbc详解:2、DriverManager管理多个数据库驱动

先上代码

static String driverName = "com.mysql.jdbc.Driver";

static String url = "jdbc:mysql://127.0.0.1:3306/mysql";

static String username = "root";

static String password = "";

@Test

public void getConnection1() {

DriverManager.setLogWriter(new PrintWriter(System.out));

try {

// 1、加载驱动,不加载驱动依然正常可以连接

// Class.forName(driverName);

// 2、获取connection

Connection conn = DriverManager.getConnection(url, username, password);

// 3、依然可以获取链接

System.out.println(conn);

// 查看已经加载的driver

Enumeration drivers = DriverManager.getDrivers();

System.out.println("------加载的diver--------");

while(drivers.hasMoreElements()) {

System.out.println(drivers.nextElement().getClass().getName());

}

} catch (Exception e) {

e.printStackTrace();

}

}

上面代码,没有手动加载驱动,但是依然可以获取连接

控制台输出信息

DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql")

trying com.mysql.jdbc.Driver

getConnection returning com.mysql.jdbc.Driver

com.mysql.jdbc.JDBC4Connection@72d8c235

------加载的diver--------

com.mysql.jdbc.Driver

com.mysql.fabric.jdbc.FabricMySQLDriver

从输出可以看到,DriverManager自动加载了com.mysql.jdbc.Driver和com.mysql.fabric.jdbc.FabricMySQLDriver这两个驱动,这也可以说明DriverManager可以管理多个驱动。

下面我们来看一下DriverManager的源码:

public class DriverManager {

static {

// 类加载时候就进行了加载数据库操作

loadInitialDrivers();

println("JDBC DriverManager initialized");

}

//其他代码省略

private static void loadInitialDrivers() {

String drivers;

try {

// AccessController.doPrivileged这个方法可以看做临时扩大该类的权限

// 读取系统jdbc.drivers的配置

drivers = AccessController.doPrivileged(new PrivilegedAction() {

public String run() {

return System.getProperty("jdbc.drivers");

}

});

} catch (Exception ex) {

drivers = null;

}

AccessController.doPrivileged(new PrivilegedAction() {

public Void run() {

// 扫描 java.sql.Driver的实现类,并加载

// 加载就按照前一篇文章一样进行驱动注册

ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class);

Iterator driversIterator = loadedDrivers.iterator();

try{

while(driversIterator.hasNext()) {

driversIterator.next();

}

} catch(Throwable t) {

// Do nothing

}

return null;

}

});

println("DriverManager.initialize: jdbc.drivers = " + drivers);

if (drivers == null || drivers.equals("")) {

return;

}

// 加载System中的jdbc.drivers参数指定的驱动,可以是多个驱动,以“:”分割

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);

}

}

}

}

加载mysql和oracle驱动,分别连接到mysql和oracle数据库

static String MYSQL_DRIVERNAME = "com.mysql.jdbc.Driver";

static String MYSQL_URL = "jdbc:mysql://127.0.0.1:3306/mysql";

static String MYSQL_USERNAME = "root";

static String MYSQL_PASSWORD = "";

static String ORALE_DRIVERNAME = "oracle.jdbc.driver.OracleDriver";

static String ORALE_URL = "jdbc:oracle:thin:@10.211.55.6:1521:ORCL";

static String ORALE_USERNAME = "system";

static String ORALE_PASSWORD = "orcl";

@Test

public void getConnection1() {

// 输出DriverManager 的日志信息到控制台

DriverManager.setLogWriter(new PrintWriter(System.out));

// 获取mysql连接

try {

// 1、加载驱动

Class.forName(MYSQL_DRIVERNAME);

// 2、获取connection

Connection conn = DriverManager.getConnection(MYSQL_URL, MYSQL_USERNAME, MYSQL_PASSWORD);

System.out.println(conn);

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

// 获取oracle连接

try {

// 1、加载驱动

Class.forName(ORALE_DRIVERNAME);

// 2、获取connection

Connection conn = DriverManager.getConnection(ORALE_URL, ORALE_USERNAME, ORALE_PASSWORD);

System.out.println(conn);

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

}

执行,控制台输出

DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql")

trying com.mysql.jdbc.Driver

getConnection returning com.mysql.jdbc.Driver

com.mysql.jdbc.JDBC4Connection@22b3428e

DriverManager.getConnection("jdbc:oracle:thin:@10.211.55.6:1521:ORCL")

trying com.mysql.jdbc.Driver

trying com.mysql.fabric.jdbc.FabricMySQLDriver

trying oracle.jdbc.OracleDriver

getConnection returning oracle.jdbc.OracleDriver

oracle.jdbc.driver.T4CConnection@28d51032

上述代码DriverManager同时连接oracle和mysql,换句话说,DriverManager同时管理着oracle和mysql两个驱动。那我们会产生疑问DriverManager到底是如果多个管理驱动的,怎么样根据我们的连接配置信息(url,密码...)获取到对应的连接?

驱动的管理或者说记录是封装成DriverInfo后放到DriverInfoCopyOnWriteArrayList,可以看做是一个线程安全的ArrayList。

private final static CopyOnWriteArrayList registeredDrivers = new CopyOnWriteArrayList();

当我们要获取连接的时候,再遍历registeredDrivers这个列表,然后使用列表中的驱动尝试连接,当获取到连接以后就停止遍历,然后返回connection

DriverManager的核心连接代码

private static Connection getConnection(

String url, java.util.Properties info, Class> caller) throws SQLException {

// 省略。。。

println("DriverManager.getConnection(\"" + url + "\")");

SQLException reason = null;

// 遍历驱动注册列表

for(DriverInfo aDriver : registeredDrivers) {

// 判断是否能使用该驱动

if(isDriverAllowed(aDriver.driver, callerCL)) {

try {

println(" trying " + aDriver.driver.getClass().getName());

// 尝试连接

/**

* 其实java.sql.Driver接口定义了一个方法判断驱动能不能接受url的连接,

* boolean acceptsURL(String url) throws SQLException;

* 这里其实先使下面代码进行判断

* if (!aDriver.driver.acceptsURL(url)) {

* continue;

* }

* 但是没有使用上面代码进行判断,我猜可能的原因是:

* 1、java官方并不要求实现acceptsURL()方法,我们平常

* 使用也很早用到这个方法。

* 2、存在一种这样的情况:某个数据库厂商协议进行升级

* 了,但是为了兼容旧的协议还是允许连接,

* acceptsURL(旧协议的url)方法,返回false,

* 起到一个提示的作用。

*/

Connection con = aDriver.driver.connect(url, info);

if (con != null) {

// Success!

println("getConnection returning " + aDriver.driver.getClass().getName());

// 没有报异常并且 connection 不为空,则返回connection

return (con);

}

} catch (SQLException ex) {

if (reason == null) {

reason = ex;

}

}

} else {

println(" skipping: " + aDriver.getClass().getName());

}

}

// if we got here nobody could connect.

if (reason != null) {

println("getConnection failed: " + reason);

throw reason;

}

println("getConnection: no suitable driver found for "+ url);

throw new SQLException("No suitable driver found for "+ url, "08001");

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值