Hibernate's default connection pool

The main thinking of this problem mainly stems from a problem in the test system. After the application runs for a few hours, it reports the problem of closing the database connection. Initially analyze a piece of recently changed code as follows:

 

Connection conn = null;
ConnectionProvider cp = null;

try{
cp = Get the connection pool class, the code here cannot be written due to *** reasons, please forgive me
conn = cp.getConnection();
.....
}finally{
cp.closeConnection(conn);
}

 

 

At first according to this code. Analyze whether the connection in the connection pool has been closed, then the closed connection obtained from the connection pool cannot be used. This is just conjecture. Code and micro-testing are the only criteria for verifying the truth (there is another way to find a god), Perform Hibernate connection pool source code analysis.

 

1. Hibernate can use the connection pool provided by a third party such as C3P0. Of course, if it is not configured, Hibernate will also provide a connection pool by default: DriverManagerConnectionProvider

 

//Connection pool, as an arrayList
private final ArrayList pool;
//connection pool size
private int poolSize;

//Constructor, create ArrayList object
public DriverManagerConnectionProvider()
  {
    this.pool = new ArrayList();

    this.checkedOut = 0;
  }

// get the connection method
public Connection getConnection()
    throws SQLException
  {
    if (log.isTraceEnabled()) log.trace("total checked-out connections: " + this.checkedOut);

    //Get the connection from the connection pool, wow, synchronization is used here. Every time you get the database connection in the connection pool, you need to lock it. It seems that the default database connection of Hibernate is not suitable for high concurrency scenarios. Also Hibernate real connection size can exceed default poolSize
    synchronized (this.pool) {
//The connection pool is not empty, it is obtained from the connection pool
      if (!(this.pool.isEmpty())) {
        int last = this.pool.size() - 1;
        if (log.isTraceEnabled()) {
          log.trace("using pooled JDBC connection, pool size: " + last);
          this.checkedOut += 1;
        }
        Connection pooled = (Connection)this.pool.remove(last);
        if (this.isolation != null) pooled.setTransactionIsolation(this.isolation.intValue());
        if (pooled.getAutoCommit() != this.autocommit) pooled.setAutoCommit(this.autocommit);
        return pooled;
      }
    }
   
   //The connection pool is empty, create a new connection and return
    log.debug("opening new JDBC connection");
    Connection conn = DriverManager.getConnection(this.url, this.connectionProps);
    if (this.isolation != null) conn.setTransactionIsolation(this.isolation.intValue());
    if (conn.getAutoCommit() != this.autocommit) conn.setAutoCommit(this.autocommit);

    if (log.isDebugEnabled()) {
      log.debug("created connection to: " + this.url + ", Isolation Level: " + conn.getTransactionIsolation());
    }
    if (log.isTraceEnabled()) this.checkedOut += 1;

    return conn;
  }

  //Haha, here is the closeConnection method, you can see that if the current connection pool size is smaller than the poolSize (poolSize defaults to 20), the connection will be put into the pool, otherwise, the connection will be closed
  public void closeConnection(Connection conn) throws SQLException
  {
    if (log.isDebugEnabled()) this.checkedOut -= 1;

    synchronized (this.pool) {
      int currentSize = this.pool.size();
      if (currentSize < this.poolSize) {
        if (log.isTraceEnabled()) log.trace("returning connection to pool, pool size: " + (currentSize + 1));
        this.pool.add(conn);
        return;
      }
    }

    log.debug("closing JDBC connection");

    conn.close();
  }

 After analysis, it can be concluded that

1. In the closeConnection method, only if the current connection pool size is smaller than poolSize (poolSize defaults to 20), the connection will be put into the pool, otherwise, the connection will be closed. So, guessing that the closed connection is put into the connection pool is wrong.
2. The connection pool needs to be locked to acquire and close the connection, so the default connection pool size is not suitable for high concurrency scenarios.
3. The real connection size of Hibernate can exceed the default poolSize.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326373981&siteId=291194637