oracle 安装mysql驱动_mysql和oracle驱动建立连接的过程

本文详细解析了JDBC连接MySQL的过程,包括com.mysql.cj.jdbc.Driver如何实现java.sql.Driver接口,DriverManager如何管理注册的驱动,以及getConnection方法内部的工作原理。通过分析连接类型如SINGLE_CONNECTION、FAILOVER_CONNECTION和REPLICATION_CONNECTION的连接建立过程,展示了从URL解析到生成Connection实例的细节。文中还提到了负载均衡和主从复制的连接策略,并提供了源码分析和示例代码。
摘要由CSDN通过智能技术生成

我们知道所有的驱动程序其实都是实现相同的JDK接口来连接数据库。这些接口其实就是JDBC接口。

那我们就从JDBC连接来看mysql驱动是怎么实现这些接口来连接数据库的。

首先写了一个简单的数据库连接程序,和mysql 建立连接

当前使用的mysql驱动是 mysql-connector-java-8.0.22.jar、jdk8.

Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatisplus?serverTimezone=Asia/Shanghai","root","123456") ;

Statement statement = connection.createStatement() ;

ResultSet resultSet = statement.executeQuery("select * from user") ;

while (resultSet.next()){

System.out.println((resultSet.getString("name")));

}

首先我们的mysql驱动类 com.mysql.cj.jdbc.Driver通过实现 java.sql.Driver ,会在应用启动时把驱动注册到DriverManager当中去。这也就是说,当我们以后需要自己开发一个驱动时,也是一样的去实现 java.sql.Driver 。

a9afd7781c9d376fdb74796a44c9ccad.png

DriverManager 内部是维护了一个 list来存储这些注册的驱动,以供后续使用的。

// List of registered JDBC drivers

private final static CopyOnWriteArrayList registeredDrivers = new CopyOnWriteArrayList<>();

04f33bbfb32e86fdf111e33eb92a512b.png

然后我们再看DriverManager怎么去getConnection的。我们可以看到getConnection里面会有一个遍历所有的Drivers,去建立连接。

同样的我们可以看到mysql建立连接的实现类是NonRegisteringDriver,接下来看下这里面是怎么建立连接的。

c1f0e40d19fec946fa200f140a64d12b.png

那我们可以看到 NonRegisteringDriver 的connect方法里面就是根据不同的连接类型 建立connection实例。

这些连接类型是定义在ConnectionUrls里面的一个枚举类  有jdbc:mysql、jdbc:mysql:loadbalance等等,就是根据我们的url来区分。

ed2cddd42aea66a8aa3f9f13af515770.png

public Connection connect(String url, Properties info) throws SQLException {

try {

try {

if (!ConnectionUrl.acceptsUrl(url)) {

return null;

} else {

ConnectionUrl conStr = ConnectionUrl.getConnectionUrlInstance(url, info);

switch(conStr.getType()) {

case SINGLE_CONNECTION:

return ConnectionImpl.getInstance(conStr.getMainHost());

case FAILOVER_CONNECTION:

case FAILOVER_DNS_SRV_CONNECTION:

return FailoverConnectionProxy.createProxyInstance(conStr);

case LOADBALANCE_CONNECTION:

case LOADBALANCE_DNS_SRV_CONNECTION:

return LoadBalancedConnectionProxy.createProxyInstance(conStr);

case REPLICATION_CONNECTION:

case REPLICATION_DNS_SRV_CONNECTION:

return ReplicationConnectionProxy.createProxyInstance(conStr);

default:

return null;

}

}

} catch (UnsupportedConnectionStringException var5) {

return null;

} catch (CJException var6) {

throw (UnableToConnectException)ExceptionFactory.createException(UnableToConnectException.class, Messages.getString("NonRegisteringDriver.17", new Object[]{var6.toString()}), var6);

}

} catch (CJException var7) {

throw SQLExceptionsMapping.translateException(var7);

}

}

那我们从最简单的 SINGLE_CONNECTION类型看 即我们url是以 jdbc:mysql开头的。实现也是很简单就是new ConnectionImpl 返回connection实例

case SINGLE_CONNECTION:

return ConnectionImpl.getInstance(conStr.getMainHost());

第二 看下常见的负载均衡连接 ,loadbalance连接时通过反射方式生成connection实例的。

caseLOADBALANCE_CONNECTION:caseLOADBALANCE_DNS_SRV_CONNECTION:return LoadBalancedConnectionProxy.createProxyInstance(conStr);

我们可以看到LoadBalanceProxy来实现的,通过java 反射,java.lang.reflect.Proxy.newProxyInstance ,通过构造器Constructor 来生成实例对象。

真正一些策略性的选择在 LoadBalanceProxy的构造方法中可以看到,默认是随机策略 random

public static LoadBalancedConnection createProxyInstance(ConnectionUrl connectionUrl) throwsSQLException {

LoadBalancedConnectionProxy connProxy= newLoadBalancedConnectionProxy(connectionUrl);return (LoadBalancedConnection)Proxy.newProxyInstance(LoadBalancedConnection.class.getClassLoader(), INTERFACES_TO_PROXY, connProxy);

}

如下图我们可以看到构造方法中几种loadbalance策略选择

RandomBalanceStrategy

BestResponseTimeBalanceStrategy

ServerAffinityStrategy

a882206ebb2028d06c1691fe485f1f31.png

第三种可以看到有主备的策略,跟loadbalance一样通过 java 反射,java.lang.reflect.Proxy.newProxyInstance ,通过构造器Constructor 来生成实例对象。

case REPLICATION_CONNECTION:

case REPLICATION_DNS_SRV_CONNECTION:

return ReplicationConnectionProxy.createProxyInstance(conStr);

所以我们可以直接看下 ReplicationConnectionProxy 代理的实现方法。我们可以看到是优先masterConnection,

master没有再选择slaveConnection,this.currentConnection = this.slavesConnection;

this.currentConnection = this.initializeMasterConnection();

try {

this.currentConnection = this.initializeMasterConnection();

} catch (SQLException var10) {

exCaught = var10;

}

if (this.currentConnection == null) {

if (!this.allowMasterDownConnections || this.slavesConnection == null) {

if (this.connectionGroup != null) {

this.connectionGroup.handleCloseConnection(this.thisAsReplicationConnection);

}

if (exCaught != null) {

throw exCaught;

} else {

throw SQLError.createSQLException(Messages.getString("ReplicationConnectionProxy.initializationWithEmptyHostsLists"), "S1009", (ExceptionInterceptor)null);

}

}

this.readOnly = true;

this.currentConnection = this.slavesConnection;

}

至此我们就能生成connection实例返回,当然这只是一个很粗的链路,里面很多细节还是需要自己亲自看看源码是怎样的。

当然我演示的代码在我的github 仓库里面有可以下载

https://github.com/xusyPersonal/springboot-mybatis-plus-demo.git  ,

这个项目是我使用springboot集成mybatis-plus的,可以简单用来学习。今天演示的连接数据库是这个测试类 MysqlConnectionTest,欢迎下载!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值