详解Mybatis中的PooledDataSource

作者:周杰伦本人 时间:2022-10-24 18:08:11 

前言

上篇Java Mybatis数据源之工厂模式文章中我们介绍了Mybatis的数据源模块的DataSource接口和它对应的实现类UnpooledDataSource、PooledDataSource,这篇文章详细介绍一下PooledDataSource
PooledDataSource使用了数据库连接池可以实现数据库连接池的重复利用,还能控制连接数据库的连接上限,实现数据库连接的统一管理,缓存数据连接信息还能防止流量突发连接数据库不及时

PooledDataSource有个PoolState状态,PoolState里保存着数据库连接信息PooledConnection,PooledConnection实现InvocationHandler接口,重写invoke方法,显然这是一个代理类,使用了JDK的 *

PooledConnection

class PooledConnection implements InvocationHandler {
   private static final Class<?>[] IFACES = new Class<?>[] { Connection.class };
   public PooledConnection(Connection connection, PooledDataSource dataSource) {
       this.hashCode = connection.hashCode();
       this.realConnection = connection;
       this.dataSource = dataSource;
       this.createdTimestamp = System.currentTimeMillis();
       this.lastUsedTimestamp = System.currentTimeMillis();
       this.valid = true;
       this.proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES, this);
   }

@Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       String methodName = method.getName();
       if (CLOSE.equals(methodName)) {
           dataSource.pushConnection(this);
           return null;
       }
       try {
           if (!Object.class.equals(method.getDeclaringClass())) {
               checkConnection();
           }
           return method.invoke(realConnection, args);
       } catch (Throwable t) {
           throw ExceptionUtil.unwrapThrowable(t);
       }
   }
}

我们看一看到构造方法中调用了Proxy.newProxyInstance()方法来生成代理类,而重写invoke方法中如果是close()就调用pushConnection()方法直接把它放入连接池而不是关闭连接,其他情况调用checkConnection()检查连接信息,代理类调用realConnection()方法,下面就看一下pushConnection()方法

PooledDataSource的pushConnection()方法

方法的功能就是把数据库连接放入连接池中:

protected void pushConnection(PooledConnection conn) throws SQLException {
       synchronized (state) {
           state.activeConnections.remove(conn);
           if (conn.isValid()) {
               if (state.idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == expectedConnectionTypeCode) {
                   state.accumulatedCheckoutTime += conn.getCheckoutTime();
                   if (!conn.getRealConnection().getAutoCommit()) {
                       conn.getRealConnection().rollback();
                   }
                   PooledConnection newConn = new PooledConnection(conn.getRealConnection(), this);
                   state.idleConnections.add(newConn);
                   newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
                   newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
                   conn.invalidate();
                   if (log.isDebugEnabled()) {
                       log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
                   }
                   state.notifyAll();
               } else {

state.accumulatedCheckoutTime += conn.getCheckoutTime();
                   if (!conn.getRealConnection().getAutoCommit()) {
                       conn.getRealConnection().rollback();
                   }
                   conn.getRealConnection().close();
                   if (log.isDebugEnabled()) {
                       log.debug("Closed connection " + conn.getRealHashCode() + ".");
                   }
                   conn.invalidate();
               }
           } else {
               if (log.isDebugEnabled()) {
                   log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");
               }
               state.badConnectionCount++;
           }
       }
   }
  • 从活跃连接集合中删除该连接

  • 如果PooledConnection有效,并且空闲连接数小于最大空闲连接数,就利用当前PooledConnection创建PooledConnection,放入空闲连接数集合中,方便下次使用,关闭当前PooledConnection对象的数据库连接,并对当前PooledConnection对象设置无效,最后唤醒其他等待的线程。如果空闲连接数大于最大空闲连接数了就关闭连接,设置当前连接无效

  • 如果PooledConnection无效,badConnectionCount加一,这个badConnectionCount是记录无效的数据库连接信息的

来源:https://blog.51cto.com/u_15460453/5375552

标签:Mybatis,PooledDataSource
0
投稿

猜你喜欢

  • Struts2拦截器 关于解决登录的问题

    2023-07-02 14:06:09
  • Java读写文件创建文件夹多种方法示例详解

    2022-11-17 01:08:48
  • android的RecyclerView实现拖拽排序和侧滑删除示例

    2023-10-06 01:33:32
  • Java设计模式之工厂模式案例详解

    2023-11-27 20:08:03
  • android侧滑菜单控件DrawerLayout使用方法详解

    2023-02-02 23:58:43
  • Maven打包jar生成javadoc文件和source文件代码实例

    2021-08-22 21:56:52
  • springboot整合通用Mapper简化单表操作详解

    2022-08-19 19:24:19
  • SpringBoot集成elasticsearch使用图文详解

    2021-06-06 16:12:47
  • Java中使用Lambda表达式和函数编程示例

    2022-05-06 03:30:40
  • android JSON解析数据 android解析天气预报

    2022-01-16 03:33:53
  • C#实现飞行棋源码

    2023-11-09 11:17:09
  • Mybatis在sqlite中无法读写byte[]类问题的解决办法

    2021-08-06 21:06:07
  • Spring中自定义数据类型转换的方法详解

    2022-10-09 02:56:51
  • 图文详解SpringBoot中Log日志的集成

    2023-05-27 09:55:13
  • Android自定义View仿大众点评星星评分控件

    2023-07-22 22:37:28
  • Java链表(Linked List)基本原理与实现方法入门示例

    2021-10-12 05:49:14
  • Android AlertDialog(对话框)实例详解

    2023-07-19 11:37:55
  • Android WebView实现长按保存图片及长按识别二维码功能

    2021-08-18 18:56:09
  • 以实例简介Java中线程池的工作特点

    2023-08-11 23:04:19
  • C#使用SQL DataAdapter数据适配代码实例

    2021-11-29 11:51:15
  • asp之家 软件编程 m.aspxhome.com