`
gaojingsong
  • 浏览: 1201576 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论
阅读更多

 



 

 

 

package org.apache.ibatis.datasource.pooled;

 

import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;

import org.apache.ibatis.logging.Log;

import org.apache.ibatis.logging.LogFactory;

 

import javax.sql.DataSource;

import java.io.PrintWriter;

import java.sql.*;

import java.util.Properties;

 

/**

 * This is a simple, synchronous, thread-safe database connection pool.

 */

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() {

    dataSource = new UnpooledDataSource();

  }

 

  public PooledDataSource(String driver, String url, String username, String password) {

    dataSource = new UnpooledDataSource(driver, url, username, password);

  }

 

  public PooledDataSource(String driver, String url, Properties driverProperties) {

    dataSource = new UnpooledDataSource(driver, url, driverProperties);

  }

 

  public PooledDataSource(ClassLoader driverClassLoader, String driver, String url, String username, String password) {

    dataSource = new UnpooledDataSource(driverClassLoader, driver, url, username, password);

  }

 

  public PooledDataSource(ClassLoader driverClassLoader, String driver, String url, Properties driverProperties) {

    dataSource = new UnpooledDataSource(driverClassLoader, driver, url, driverProperties);

  }

 

  public Connection getConnection() throws SQLException {

    return popConnection(dataSource.getUsername(), dataSource.getPassword()).getProxyConnection();

  }

 

  public Connection getConnection(String username, String password) throws SQLException {

    return popConnection(username, password).getProxyConnection();

  }

 

  public void setLoginTimeout(int loginTimeout) throws SQLException {

    DriverManager.setLoginTimeout(loginTimeout);

  }

 

  public int getLoginTimeout() throws SQLException {

    return DriverManager.getLoginTimeout();

  }

 

  public void setLogWriter(PrintWriter logWriter) throws SQLException {

    DriverManager.setLogWriter(logWriter);

  }

 

  public PrintWriter getLogWriter() throws SQLException {

    return DriverManager.getLogWriter();

  }

 

  public void setDriver(String driver) {

    dataSource.setDriver(driver);

    forceCloseAll();

  }

 

  public void setUrl(String url) {

    dataSource.setUrl(url);

    forceCloseAll();

  }

 

  public void setUsername(String username) {

    dataSource.setUsername(username);

    forceCloseAll();

  }

 

  public void setPassword(String password) {

    dataSource.setPassword(password);

    forceCloseAll();

  }

 

  public void setDefaultAutoCommit(boolean defaultAutoCommit) {

    dataSource.setAutoCommit(defaultAutoCommit);

    forceCloseAll();

  }

 

  public void setDefaultTransactionIsolationLevel(Integer defaultTransactionIsolationLevel) {

    dataSource.setDefaultTransactionIsolationLevel(defaultTransactionIsolationLevel);

    forceCloseAll();

  }

 

 

  public void setDriverProperties(Properties driverProps) {

    dataSource.setDriverProperties(driverProps);

    forceCloseAll();

  }

 

  /**

   * The maximum number of active connections

   *

   * @param poolMaximumActiveConnections The maximum number of active connections

   */

  public void setPoolMaximumActiveConnections(int poolMaximumActiveConnections) {

    this.poolMaximumActiveConnections = poolMaximumActiveConnections;

    forceCloseAll();

  }

 

  /**

   * The maximum number of idle connections

   *

   * @param poolMaximumIdleConnections The maximum number of idle connections

   */

  public void setPoolMaximumIdleConnections(int poolMaximumIdleConnections) {

    this.poolMaximumIdleConnections = poolMaximumIdleConnections;

    forceCloseAll();

  }

 

  /**

   * The maximum time a connection can be used before it *may* be

   * given away again.

   *

   * @param poolMaximumCheckoutTime The maximum time

   */

  public void setPoolMaximumCheckoutTime(int poolMaximumCheckoutTime) {

    this.poolMaximumCheckoutTime = poolMaximumCheckoutTime;

    forceCloseAll();

  }

 

  /**

   * The time to wait before retrying to get a connection

   *

   * @param poolTimeToWait The time to wait

   */

  public void setPoolTimeToWait(int poolTimeToWait) {

    this.poolTimeToWait = poolTimeToWait;

    forceCloseAll();

  }

 

  /**

   * The query to be used to check a connection

   *

   * @param poolPingQuery The query

   */

  public void setPoolPingQuery(String poolPingQuery) {

    this.poolPingQuery = poolPingQuery;

    forceCloseAll();

  }

 

  /**

   * Determines if the ping query should be used.

   *

   * @param poolPingEnabled True if we need to check a connection before using it

   */

  public void setPoolPingEnabled(boolean poolPingEnabled) {

    this.poolPingEnabled = poolPingEnabled;

    forceCloseAll();

  }

 

  /**

   * If a connection has not been used in this many milliseconds, ping the

   * database to make sure the connection is still good.

   *

   * @param milliseconds the number of milliseconds of inactivity that will trigger a ping

   */

  public void setPoolPingConnectionsNotUsedFor(int milliseconds) {

    this.poolPingConnectionsNotUsedFor = milliseconds;

    forceCloseAll();

  }

 

  public String getDriver() {

    return dataSource.getDriver();

  }

 

  public String getUrl() {

    return dataSource.getUrl();

  }

 

  public String getUsername() {

    return dataSource.getUsername();

  }

 

  public String getPassword() {

    return dataSource.getPassword();

  }

 

  public boolean isAutoCommit() {

    return dataSource.isAutoCommit();

  }

 

  public Integer getDefaultTransactionIsolationLevel() {

    return dataSource.getDefaultTransactionIsolationLevel();

  }

 

  public Properties getDriverProperties() {

    return dataSource.getDriverProperties();

  }

 

  public int getPoolMaximumActiveConnections() {

    return poolMaximumActiveConnections;

  }

 

  public int getPoolMaximumIdleConnections() {

    return poolMaximumIdleConnections;

  }

 

  public int getPoolMaximumCheckoutTime() {

    return poolMaximumCheckoutTime;

  }

 

  public int getPoolTimeToWait() {

    return poolTimeToWait;

  }

 

  public String getPoolPingQuery() {

    return poolPingQuery;

  }

 

  public boolean isPoolPingEnabled() {

    return poolPingEnabled;

  }

 

  public int getPoolPingConnectionsNotUsedFor() {

    return poolPingConnectionsNotUsedFor;

  }

 

  /**

   * Closes all active and idle connections in the pool

   */

  public void forceCloseAll() {

    synchronized (state) {

      expectedConnectionTypeCode = assembleConnectionTypeCode(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword());

      for (int i = state.activeConnections.size(); i > 0; i--) {

        try {

          PooledConnection conn = (PooledConnection) state.activeConnections.remove(i - 1);

          conn.invalidate();

 

          Connection realConn = conn.getRealConnection();

          if (!realConn.getAutoCommit()) {

            realConn.rollback();

          }

          realConn.close();

        } catch (Exception e) {

          // ignore

        }

      }

      for (int i = state.idleConnections.size(); i > 0; i--) {

        try {

          PooledConnection conn = (PooledConnection) state.idleConnections.remove(i - 1);

          conn.invalidate();

 

          Connection realConn = conn.getRealConnection();

          if (!realConn.getAutoCommit()) {

            realConn.rollback();

          }

          realConn.close();

        } catch (Exception e) {

          // ignore

        }

      }

    }

    if (log.isDebugEnabled()) {

      log.debug("PooledDataSource forcefully closed/removed all connections.");

    }

  }

 

  public PoolState getPoolState() {

    return state;

  }

 

  private int assembleConnectionTypeCode(String url, String username, String password) {

    return ("" + url + username + password).hashCode();

  }

 

  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++;

      }

    }

  }

 

  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.size() > 0) {

          // Pool has available connection

          conn = (PooledConnection) 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);

            Connection realConn = conn.getRealConnection();

            if (log.isDebugEnabled()) {

              log.debug("Created connection " + conn.getRealHashCode() + ".");

            }

          } else {

            // Cannot create new connection

            PooledConnection oldestActiveConnection = (PooledConnection) 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()) {

                oldestActiveConnection.getRealConnection().rollback();

              }

              conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);

              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;

  }

 

  /**

   * Method to check to see if a connection is still usable

   *

   * @param conn - the connection to check

   * @return True if the connection is still usable

   */

  protected boolean pingConnection(PooledConnection conn) {

    boolean result = true;

 

    try {

      result = !conn.getRealConnection().isClosed();

    } catch (SQLException e) {

      if (log.isDebugEnabled()) {

        log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());

      }

      result = false;

    }

 

    if (result) {

      if (poolPingEnabled) {

        if (poolPingConnectionsNotUsedFor > 0 && conn.getTimeElapsedSinceLastUse() > poolPingConnectionsNotUsedFor) {

          try {

            if (log.isDebugEnabled()) {

              log.debug("Testing connection " + conn.getRealHashCode() + " ...");

            }

            Connection realConn = conn.getRealConnection();

            Statement statement = realConn.createStatement();

            ResultSet rs = statement.executeQuery(poolPingQuery);

            rs.close();

            statement.close();

            if (!realConn.getAutoCommit()) {

              realConn.rollback();

            }

            result = true;

            if (log.isDebugEnabled()) {

              log.debug("Connection " + conn.getRealHashCode() + " is GOOD!");

            }

          } catch (Exception e) {

            log.warn("Execution of ping query '" + poolPingQuery + "' failed: " + e.getMessage());

            try {

              conn.getRealConnection().close();

            } catch (Exception e2) {

              //ignore

            }

            result = false;

            if (log.isDebugEnabled()) {

              log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());

            }

          }

        }

      }

    }

    return result;

  }

 

  /**

   * Unwraps a pooled connection to get to the 'real' connection

   *

   * @param conn - the pooled connection to unwrap

   * @return The 'real' connection

   */

  public static Connection unwrapConnection(Connection conn) {

    if (conn instanceof PooledConnection) {

      return ((PooledConnection) conn).getRealConnection();

    } else {

      return conn;

    }

  }

 

  protected void finalize() throws Throwable {

    forceCloseAll();

  }

 

  public <T> T unwrap(Class<T> iface) throws SQLException {

    throw new UnsupportedOperationException();

  }

 

  public boolean isWrapperFor(Class<?> iface) throws SQLException {

    throw new UnsupportedOperationException();

  }

}

 

  • 大小: 5.1 KB
0
6
分享到:
评论

相关推荐

    ibatis源码,ibatis源码 ibatis源码 ibatis源码

    通过阅读和理解iBatis的源码,我们可以更深入地了解其设计思路,从而更好地利用这个框架,提升我们的开发效率和代码质量。同时,源码学习也能帮助我们解决实际项目中遇到的问题,增强我们在ORM领域的专业技能。

    ibatis源码

    阅读和分析iBATIS源码,可以帮助开发者: 1. **理解工作原理**:了解iBATIS如何解析SQL映射文件,如何执行SQL,如何处理结果集映射,以及事务控制等关键流程。 2. **优化性能**:通过源码,可以找出可能的性能瓶颈...

    最新ibatis 源码

    ibatis源码 学习参考 对于学习ibatis很有帮助

    iBATIS框架源码剖析

    iBATIS框架源码剖析

    ibatis源码+api文档+jar包

    1. 源码阅读:源码中包含Ibatis的所有核心组件,如SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession等。通过阅读源码,可以深入了解其工作原理,例如如何加载配置文件、如何创建和管理SqlSession、如何执行...

    iBATIS框架源码剖析源码

    通过深入分析iBATIS的源码,开发者不仅可以了解其工作原理,还能学习到设计模式、数据库访问的最佳实践以及如何优雅地处理数据库操作。对于提升Java开发者的技能和理解数据库访问层的实现有极大的帮助。在实际开发中...

    ibatis框架源码剖析光盘资料

    《ibatis框架源码剖析》是一本深入探讨mybatis前身——ibatis的源码解析书籍。通过对源码的深入分析,我们可以理解ibatis的核心机制,掌握数据库操作的底层原理,从而更好地利用和优化这个强大的持久层框架。在这个...

    iBatis框架源码剖析

    iBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目。于2010年6月16号被谷歌托管,改名为MyBatis。是一个基于SQL映射支持Java和·NET的持久层框架。

    iBATIS2.3.4 jar包及源码

    在本主题中,我们关注的是iBATIS 2.3.4版本的jar包及其源码。 首先,`ibatis-2.3.4.jar` 是包含iBATIS核心库的二进制文件,用于在Java应用中集成iBATIS。这个jar包包含了所有必要的类和资源,如SQL映射接口、数据...

    springMVC+ibatis的源码

    通过学习和分析这个源码,开发者不仅可以深入了解SpringMVC和iBatis的协同工作原理,还可以掌握如何在Eclipse这样的IDE中配置和运行这样的项目。这有助于提升对MVC模式的理解,提高数据库操作的能力,以及熟练运用...

    ibatis源码及实例

    iBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目。最初侧重于密码软件的开发,现在是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data ...

    iBatis源码jar包以后上传

    这个“iBatis源码jar包以后上传”可能指的是将要分享或者提供iBatis的源码jar包,以便于开发者深入学习和理解其内部工作原理。 首先,让我们来了解一下iBatis的基本概念和工作流程。iBatis的核心是SQL Map配置文件...

    ibatis源码 例子

    ibatis 源码 例子 包含 源码,jar都有 部分代码 package com.icss.dao; import java.io.IOException; import java.io.Reader; import java.sql.SQLException; import java.util.List; import ...

    ibatis2.3源码

    MyEclipse是一款强大的Java EE集成开发工具,支持直接导入外部项目源码,便于开发者进行代码阅读、学习和调试。"有需要的朋友可以看看"暗示这个源码包对想要深入理解iBATIS工作原理或进行二次开发的开发者非常有价值...

    IBatis源码+xsd+帮助

    1. **动态SQL**:IBatis的核心功能之一就是动态SQL,它允许在SQL语句中使用条件判断,使SQL更具灵活性。 2. **映射文件和映射器接口**:源码中包含了Mapper接口和对应的XML映射文件,展示了如何定义和执行SQL查询。 ...

    ibatis 2.3.4 源码

    ibatis 2.3.4 的源码 public abstract Object insert(String paramString, Object paramObject) throws SQLException; public abstract Object insert(String paramString) throws SQLException; public ...

    ibatis 学习源码

    PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" "http://www.ibatis.com/dtd/sql-map-config-2.dtd"&gt; cacheModelsEnabled="true" enhancementEnabled="true" lazyLoadingEnabled="true" ...

Global site tag (gtag.js) - Google Analytics