mybatis -- 数据源与连接池

一、MyBatis数据源DataSource分类
在这里插入图片描述
MyBatis把数据源DataSource分为三种:

  • UNPOOLED 不使用连接池的数据源
  • POOLED 使用连接池的数据源
  • JNDI 使用JNDI实现的数据源,从tomcat中获取一个内置的数据库连接池

MyBatis内部定义了实现java.sql.DataSource接口的UnpooledDataSource,PooledDataSource类来表示UNPOOLED、POOLED类型的数据源。
在这里插入图片描述
二、数据源DataSource的创建过程
DataSource对象的创建发生在MyBatis初始化的过程中。
在XML配置文件中,使用<dataSource>元素来配置数据源:

<dataSource type="POOLED">
	<!-- 配置数据库信息 -->
	<property name="driver" value="${mysqlDriver}"/>
	<property name="url" value="${mysqlURL}"/>
	<property name="username" value="${mysqlUser}"/>
	<property name="password" value="${mysqlPaw}"/>
</dataSource>
  1. MyBatis在初始化时,解析此文件,根据的type属性来创建相应类型的的数据源DataSource。
  2. MyBatis是通过工厂模式来创建数据源DataSource对象的,其定义了抽象的工厂接口 : DataSourceFactory, 通过其 getDataSource()方法返回数据源DataSource:
public interface DataSourceFactory {
  	void setProperties(Properties props);
  	DataSource getDataSource();       //生产DataSource
}

上述三种类型,对应一下DateSource工厂
在这里插入图片描述
3. 创建DataSource实例后,将其放到Configuration对象内的Environment 中, 供以后使用。

三、DataSource什么时候创建Connection对象
当需要创建SqlSession对象并需要执行SQL语句时,MyBatis才会去调用dataSource对象来创建java.sql.Connection对象。即Connection对象的创建一直延迟到执行SQL语句。触发以下方法:

protected void openConnection() throws SQLException {
       if (log.isDebugEnabled()) 
            log.debug("Opening JDBC Connection");
       connection = dataSource.getConnection();
       if (level != null) 
             connection.setTransactionIsolation(level.getLevel());
        setDesiredAutoCommit(autoCommmit);
    }

四、不使用连接池的UnpooledDataSource
使用UnpooledDataSource实例的getConnection()方法, 每调用一次都会通过DriverManager. getConnection() 返回新的Connection实例。

public Connection getConnection() throws SQLException
{
    return doGetConnection(username, password);
}
 
/*
 *  获取数据连接
 */
private Connection doGetConnection(Properties properties) throws SQLException
{
    //1.初始化驱动
    initializeDriver();
    //2.从DriverManager中获取连接,获取新的Connection对象
    Connection connection = DriverManager.getConnection(url, properties);
    //3.配置connection属性
    configureConnection(connection);
    return connection;
}

UnpooledDataSource会做以下事情:

  1. 初始化驱动:判断driver驱动是否已经加载到内存中,如果还没有,则会动态地加载driver类,并实例化一个Driver对象,使用DriverManager.registerDriver()将其注册到内存中,供后续使用
  2. 创建Connection对象:使用DriverManager.getConnection()方法创建连接。
  3. 配置Connection对象:设置是否自动提交autoCommit和隔离级别isolationLevel。
  4. 返回Connection对象。
    在这里插入图片描述

五、使用连接池的PooledDataSource

PooledDataSource 将Connection对象包裹成PooledConnection对象放到容器中维护。 存在两种状态: 空闲状态(idle)和活动状态(active),这些对象分别被存储到容器内的idleConnections和activeConnections两个List集合中。

使用时,会优先从空闲集合中取PooledConnection对象,若没有,则看活动集合是否已满,未满就创建一个连接,添加到活动集合中,若已满,则做先进入集合的对象是否已过期,若没有过期,则线程等待。(在synchronized同步代码块中执行)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200508104452251.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzE5MTc0Nw==,size_16,color_FFFFFF,t_70)

怎样实现Connection对象调用了close()方法,而实际是将其添加到连接池中?
使用代理模式,为真正的Connection对象创建一个代理对象,当代理对象执行close()方法时,不调用真正Connection对象的close()方法,而是将Connection对象添加到连接池中。

PooledConnection对象实现了InvocationHandler接口,proxyConnection对象也是根据这个它来生成的代理对象,当调用PooledDataSource的getConnection()方法返回的就是这个代理对象。当调用close方法时,会调用代理对象的invoke方法。

public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
    String methodName = method.getName();
    //当调用关闭的时候,回收此Connection到PooledDataSource中
    if (CLOSE.hashCode() == methodName.hashCode() && CLOSE.equals(methodName)) {
          dataSource.pushConnection(this);
          return null;
    } else {
      try {
        if (!Object.class.equals(method.getDeclaringClass())) {
          checkConnection();
        }
        return method.invoke(realConnection, args);
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值