Mybatis the connection pool

I. Introduction

Connection pooling there are many, the most familiar example c3p0, DBCP, druid and so on.

mybatis supports three built-in data source types:

  • Pooled:DataSource implement interfaces, and use the pool of ideas.
  • UNPooled:It is also achieved dataSource interface, but this type of thinking did not use the pool.
  • JDNI:JDNI server using technology implemented, and acquires the connection between the different servers is not the same pool.

Note: If the project is not a web of war or maven project, it can not be used. For example, Tomcat server is using DBCP connection pool.

How configuration data source Mybatis species, as follows:

<!-- 数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>

In the dataSource attribute, type tag can specify the types of data sources used.

Two, UnPooled

1, starting from source to obtain connections.

@Override
  public Connection getConnection() throws SQLException {
    return doGetConnection(username, password);
  }

2, and then re-enter the doGetConnection()process:

private Connection doGetConnection(String username, String password) throws SQLException {
    // 实例化一个集合
    Properties props = new Properties();
    if (driverProperties != null) {
      props.putAll(driverProperties);
    }
    // 判断用户名是否为空
    if (username != null) {
      props.setProperty("user", username);
    }
    // 判断密码是否为空
    if (password != null) {
      props.setProperty("password", password);
    }
    return doGetConnection(props);
  }

3, returned to a case doGetConnection(), another method which is overloaded.

private Connection doGetConnection(Properties properties) throws SQLException {
    // 初始化
    initializeDriver();
    // 获取一个连接对象
    Connection connection = DriverManager.getConnection(url, properties);
    configureConnection(connection);
    return connection;
  }

4, the first line of code, called initializeDriver()methods.

private synchronized void initializeDriver() throws SQLException {
    if (!registeredDrivers.containsKey(driver)) {
      Class<?> driverType;
      try {
        if (driverClassLoader != null) {
            // 使用反射获取到连接驱动
          driverType = Class.forName(driver, true, driverClassLoader);
        } else {
          driverType = Resources.classForName(driver);
        }
        // DriverManager requires the driver to be loaded via the system ClassLoader.
        // http://www.kfu.com/~nsayer/Java/dyn-jdbc.html
        // 实例化连接驱动
          Driver driverInstance = (Driver)driverType.newInstance();
          // 注册驱动
        DriverManager.registerDriver(new DriverProxy(driverInstance));
        registeredDrivers.put(driver, driverInstance);
      } catch (Exception e) {
        throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
      }
    }
  }

General process:

  • While obtaining a connection object, call initializeDriver()the method to determine whether a connection has been registered drivers.
  • Complete the registration drive, use DriverManager.getConnectionget a connection object.
  • The connection object to the configureConnection()method, and set up automatic commit the transaction, and the transaction isolation level.
private void configureConnection(Connection conn) throws SQLException {
    if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
      conn.setAutoCommit(autoCommit);
    }
    if (defaultTransactionIsolationLevel != null) {
      conn.setTransactionIsolation(defaultTransactionIsolationLevel);
    }
  }

This approach is not to have thought of the connection pool, or if you frequently create and destroy objects connected, will affect the efficiency of the program.

Three, Pooled

Let's look at the idea of ​​using connection pooling data source implementation.

Prior to this first is that what is the connection pool, the connection pool is a container for storing the connection object. The container is a collection, and must be thread-safe, that is, two threads can not get the same connection object. But also have characteristics queue: FIFO principle.

The benefits of using connection pooling: Avoid frequent create and close the overhead caused by database connection, save system resources.

1, starting with the beginning of the source code to get a connection.

@Override
  public Connection getConnection() throws SQLException {
    return popConnection(dataSource.getUsername(), dataSource.getPassword()).getProxyConnection();
  }

2, call the popConnection()method (a bit long).

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) {
          // 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;
  }

Analysis:

1, it is determined whether there is an idle connection object is connected to the pool, there are directly returned.

2, if the connection is not idle connection pool, first determine whether the active connection pool is less than the maximum number of database connections bearer, is less than the re-create a new connection object.

3, but if the connection pool has reached the maximum number of bearers, then returns the first out put in the connection pool incoming connections (oldest).

IV Summary

About JDNI not use the shared, because blog is not clear, I did not go inside the details of the implementation study, but the latter will have to supplement it.

What about Mybatis in addition uses two data sources, also concluded over, its main thought is about the pool, as well as the benefits of using connection pooling brings.

Finally, the above are self-study summary, if not place welcome message corrections.

Thanks for reading!

Guess you like

Origin www.cnblogs.com/fenjyang/p/11537381.html