Mybatis連接池


Mybatis連接池

xml 形式配置 DataSource

[img](javascript:void(0)😉

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
  <properties resource="/com/cn/cs/config.properties"/>
  <environments default="development">
    <environment>
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${oracle.driver}"/>
        <property name="url" value="${oracle.url}"/>
        <property name="username" value="${oracle.username}"/>
        <property name="password" value="${oracle.password}"/>
        <property name="poolMaximumActiveConnections" value="10"/> <!--最大活躍連接數 -->
        <property name="poolMaximumIdleConnections" value="5"/>  <!--最大空閑連接數-->
        <property name="poolTimeToWait" value="20000"/>  <!--創建連接時最大等待時間20s-->
      </dataSource>
    </environment>
  </environments>
  <mappers>
      <mapper resource="/com/cn/cs/mapping/UserCsMapper.xml"/>  
  </mappers>
</configuration>
 

[img](javascript:void(0)😉

mybatis 中 DataSource 節點有一個 type 屬性. 有三個可選值: pooled(連接池), unpooled(非連接池), jndi

mybatis 內部定義了一個 DataSourceFactory 接口

[img](javascript:void(0)😉

public interface DataSourceFactory {

  void setProperties(Properties props);

  DataSource getDataSource();

}

[img](javascript:void(0)😉

根據 type 屬性值分別對應實現類.

  pooled --> PooledDataSourceFactory

​ unpooled --> UnpooledDataSourceFactory

  jndi--> JndiDataSourceFactory

img

這三個實現類都實現了 DataSourceFactory 的 DataSource getDataSource() 方法.

PooledDataSourceFactory.getDataSource() 返回 PooledDataSource.

UnpooledDataSourceFactory.getDataSource() 返回 UnpooledDataSource

JndiDataSourceFactory.getDataSource() 返回 環境中的 DataSource

DataSource 將會保存在 Environment 的靜態內部類 Builder 中.

連接池的初始化

dataSource 此時只會保存好配置信息. 連接池此時並沒有創建好連接. 只有當程序在調用操作數據庫的方法時, 才會出示化連接.

管理連接池的類為 PooledDateSource 這個類中有一個獲取連接的方法.

這個方法會先判斷是否有空閑連接, 有的話會直接將連接取出來. 如果沒有則判斷當前活躍的連接是否大於最大空閑連接數. 如果小於則創建一個新的連接.

否則將舊的連接刪掉一個, 並創建一個新的連接.

[img](javascript:void(0)😉

private PooledConnection popConnection(String username, String password) throws SQLException {
    boolean countedWait = false;
    PooledConnection conn = null;
    long t = System.currentTimeMillis();
    int localBadConnectionCount = 0;

    while (conn == null) {
      synchronized (state) {
        if (!state.idleConnections.isEmpty()) {
          // Pool has available connection
          conn = state.idleConnections.remove(0);
          if (log.isDebugEnabled()) {
            log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
          }
        } else {
          // Pool does not have available connection
          if (state.activeConnections.size() < poolMaximumActiveConnections) {
            // Can create new connection
            conn = new PooledConnection(dataSource.getConnection(), this);
            if (log.isDebugEnabled()) {
              log.debug("Created connection " + conn.getRealHashCode() + ".");
            }
          } else {
            // Cannot create new connection
            PooledConnection oldestActiveConnection = state.activeConnections.get(0);
            long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
            if (longestCheckoutTime > poolMaximumCheckoutTime) {
              // Can claim overdue connection
              state.claimedOverdueConnectionCount++;
              state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
              state.accumulatedCheckoutTime += longestCheckoutTime;
              state.activeConnections.remove(oldestActiveConnection);
              if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
                try {
                  oldestActiveConnection.getRealConnection().rollback();
                } catch (SQLException e) {
                  /*
                     Just log a message for debug and continue to execute the following
                     statement like nothing happened.
                     Wrap the bad connection with a new PooledConnection, this will help
                     to not interrupt current executing thread and give current thread a
                     chance to join the next competition for another valid/good database
                     connection. At the end of this loop, bad {@link @conn} will be set as null.
                   */
                  log.debug("Bad connection. Could not roll back");
                }
              }
              conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
              conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());
              conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());
              oldestActiveConnection.invalidate();
              if (log.isDebugEnabled()) {
                log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
              }
            } else {
              // Must wait
              try {
                if (!countedWait) {
                  state.hadToWaitCount++;
                  countedWait = true;
                }
                if (log.isDebugEnabled()) {
                  log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
                }
                long wt = System.currentTimeMillis();
                state.wait(poolTimeToWait);
                state.accumulatedWaitTime += System.currentTimeMillis() - wt;
              } catch (InterruptedException e) {
                break;
              }
            }
          }
        }
        if (conn != null) {
          // ping to server and check the connection is valid or not
          if (conn.isValid()) {
            if (!conn.getRealConnection().getAutoCommit()) {
              conn.getRealConnection().rollback();
            }
            conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));
            conn.setCheckoutTimestamp(System.currentTimeMillis());
            conn.setLastUsedTimestamp(System.currentTimeMillis());
            state.activeConnections.add(conn);
            state.requestCount++;
            state.accumulatedRequestTime += System.currentTimeMillis() - t;
          } else {
            if (log.isDebugEnabled()) {
              log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
            }
            state.badConnectionCount++;
            localBadConnectionCount++;
            conn = null;
            if (localBadConnectionCount > (poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance)) {
              if (log.isDebugEnabled()) {
                log.debug("PooledDataSource: Could not get a good connection to the database.");
              }
              throw new SQLException("PooledDataSource: Could not get a good connection to the database.");
            }
          }
        }
      }

    }

    if (conn == null) {
      if (log.isDebugEnabled()) {
        log.debug("PooledDataSource: Unknown severe error condition.  The connection pool returned a null connection.");
      }
      throw new SQLException("PooledDataSource: Unknown severe error condition.  The connection pool returned a null connection.");
    }

    return conn;
  }

img


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM