Mybatis DataSource Connection 相关源码

来源:互联网 发布:淘宝店铺每日工作流程 编辑:程序博客网 时间:2024/06/16 18:59

MyBatis把数据源DataSource分为3种(xml配置):

  1. UNPOOLED 不使用连接池的数据源
  2. POOLED 使用连接池的数据源
  3. JNDI 使用JNDI实现的数据源
public class PooledDataSource implements DataSource {  private static final Log log = LogFactory.getLog(PooledDataSource.class);  private final PoolState state = new PoolState(this);  private final UnpooledDataSource dataSource;  // OPTIONAL CONFIGURATION FIELDS  protected int poolMaximumActiveConnections = 10;  protected int poolMaximumIdleConnections = 5;  protected int poolMaximumCheckoutTime = 20000;  protected int poolTimeToWait = 20000;  protected String poolPingQuery = "NO PING QUERY SET";  protected boolean poolPingEnabled = false;  protected int poolPingConnectionsNotUsedFor = 0;  private int expectedConnectionTypeCode;  public PooledDataSource() {    // pooledDataSource 带有unpooledDataSource的实例对象,只为了创建新连接,pooledDataSource可理解为维护了连接池的unpooledDataSource    dataSource = new UnpooledDataSource();  }  ...  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++;      }    }  }1.  先看是否有空闲(idle)状态下的PooledConnection对象,如果有,就直接返回一个可用的PooledConnection对象;否则进行第2步。2.  查看活动状态的PooledConnection池activeConnections是否已满;如果没有满,则创建一个新的PooledConnection对象,然后放到activeConnections池中,然后返回此PooledConnection对象;否则进行第三步;3.  看最先进入activeConnections池中的PooledConnection对象是否已经过期:如果已经过期,从activeConnections池中移除此对象,然后创建一个新的PooledConnection对象,添加到activeConnections中,然后将此对象返回;否则进行第4步。  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) {                  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) {          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 + 3)) {              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;  }  ...}

创建DataSource:

使用配置文件,对DataSource进行初始化

public class UnpooledDataSourceFactory implements DataSourceFactory {  private static final String DRIVER_PROPERTY_PREFIX = "driver.";  private static final int DRIVER_PROPERTY_PREFIX_LENGTH = DRIVER_PROPERTY_PREFIX.length();  protected DataSource dataSource;  public UnpooledDataSourceFactory() {    this.dataSource = new UnpooledDataSource();  }  @Override  public void setProperties(Properties properties) {    Properties driverProperties = new Properties();    MetaObject metaDataSource = SystemMetaObject.forObject(dataSource);    for (Object key : properties.keySet()) {      String propertyName = (String) key;      if (propertyName.startsWith(DRIVER_PROPERTY_PREFIX)) {        String value = properties.getProperty(propertyName);        driverProperties.setProperty(propertyName.substring(DRIVER_PROPERTY_PREFIX_LENGTH), value);      } else if (metaDataSource.hasSetter(propertyName)) {        String value = (String) properties.get(propertyName);        Object convertedValue = convertValue(metaDataSource, propertyName, value);        metaDataSource.setValue(propertyName, convertedValue);      } else {        throw new DataSourceException("Unknown DataSource property: " + propertyName);      }    }    if (driverProperties.size() > 0) {      metaDataSource.setValue("driverProperties", driverProperties);    }  }  @Override  public DataSource getDataSource() {    return dataSource;  }  private Object convertValue(MetaObject metaDataSource, String propertyName, String value) {    Object convertedValue = value;    Class<?> targetType = metaDataSource.getSetterType(propertyName);    if (targetType == Integer.class || targetType == int.class) {      convertedValue = Integer.valueOf(value);    } else if (targetType == Long.class || targetType == long.class) {      convertedValue = Long.valueOf(value);    } else if (targetType == Boolean.class || targetType == boolean.class) {      convertedValue = Boolean.valueOf(value);    }    return convertedValue;  }}
public class PooledDataSourceFactory extends UnpooledDataSourceFactory {  public PooledDataSourceFactory() {    this.dataSource = new PooledDataSource();  }}

DataSource创建Connection:

简单调用:

String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession = sqlSessionFactory.openSession();sqlSession.selectList("SELECT * FROM STUDENTS");

DefaultSqlSessionFactory:

@Overridepublic SqlSession openSession() {    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);}private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {    Transaction tx = null;    try {      final Environment environment = configuration.getEnvironment();      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);      final Executor executor = configuration.newExecutor(tx, execType);      return new DefaultSqlSession(configuration, executor, autoCommit);    } catch (Exception e) {      closeTransaction(tx); // may have fetched a connection so lets call close()      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);    } finally {      ErrorContext.instance().reset();    }  }

JdbcTransactionFactory:

@Overridepublic Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {    return new JdbcTransaction(ds, level, autoCommit);}

JdbcTransaction:

public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {    dataSource = ds;    level = desiredLevel;    autoCommmit = desiredAutoCommit;}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);  }
0 0