How does aggressive connection release work in Hibernate

Imagine having a tool that can automatically detect JPA and Hibernate performance issues. Wouldn’t that be just awesome?

Well, Hypersistence Optimizer is that tool! And it works with Spring Boot, Spring Framework, Jakarta EE, Java EE, Quarkus, or Play Framework.

So, enjoy spending your time on the things you love rather than fixing performance issues in your production system on a Saturday night!

Hibernate connection providers

Hibernate needs to operate both in Java EE and stand-alone environments, and the database connectivity configuration can be done either declaratively or programmatically.

To accommodate JDBC Driver connections as well as RESOURCE_LOCAL and JTA DataSource configurations, Hibernate defines its own connection factory abstraction, represented by the org.hibernate.engine.jdbc.connections.spi.ConnectionProvider interface.

public interface ConnectionProvider 
    extends Service, Wrapped {

    public Connection getConnection() 
        throws SQLException;

    public void closeConnection(Connection connection) 
        throws SQLException;
    
    public boolean supportsAggressiveRelease();
}

Because the connection provider might influence transaction response time, Hibernate offers multiple implementations for the ConnectionProvider interface:

  • DriverManagerConnectionProvider – which uses a rudimentary connection pooling implementation, so it’s only meant for testing scenarios
  • C3P0ConnectionProvider – uses c3p0 for connection pooling and it’s a much better alternative than the previous option
  • DatasourceConnectionProvider – the most flexible choice is to use an externally configured DataSource and provide it to Hibernate through the non-jta-data-source or a jta-data-source element, or by setting the hibernate.connection.datasource configuration property.

The DatasourceConnectionProvider is the most flexible alternative because it allows proxying the DataSource with connection pooling, connection monitoring and statement logging semantics in a transparent manner.

Hibernate connection release modes

Hibernate defers the database connection acquisition until the current transaction has to execute its first SQL statement (either triggered by a read or a write operation). This optimization allows Hibernate to reduce the physical transaction interval, therefore increasing the chance of getting a connection from the pool.

The connection release strategy is controlled through the hibernate.connection.release_mode property which can take the following values:

Value Description
after_transaction Once acquired, the database connection is released only after the current transaction either commits or rolls back.
after_statement The connection is released after each statement execution and reacquired prior to running the next statement. Although not required by either JDBC or JTA specifications, this strategy is meant to prevent application servers from mistakenly detecting a connection leak between successive EJB (Enterprise Java Beans) calls
auto This is the default value, and for RESOURCE_LOCAL transactions it uses the after_transaction mode, while for JTA transactions it falls back to after_statement.

For more details about why aggresive connection release mode was introduced, check out the HHH-1287 Hibernate Jira issue.

For JTA transactions, the default mode might be too strict since not all Java EE application servers exhibit the same behavior for managing transactional resources. This way, it’s important to check if database connections can be closed outside of the EJB component that triggered the connection acquisition event. Spring-based enterprise systems don’t use Enterprise Java Beans, and, even when using a stand-alone JTA transaction manager, the after_transaction connection release mode might be just fine.

It’s somehow intuitive that the after_statement mode incurs some performance penalty associated with the frequent acquisition/releasing connection cycles. For this reason, the following test measures the connection acquisition overhead when using Bitronix in a Spring application context. Each transaction executes the same statement (fetching the current timestamp) for a given number of times (represented on the x-axis).

The y-axis captures the recorded transaction response times for both after_statement and after_transaction connection release modes.

Connection Release Mode

The more statements a transaction will execute, the greater the penalty of reacquiring the associated database connection from the underlying connection pool. To better visualize the connection acquisition overhead, the test runs up to 10000 statements, even if this number is probably too high for the typical OLTP transaction.

Ideally, database transactions should be as short as possible, and the number of statements shouldn’t be too high either. This requirement stems from the fact that the number of pooled connections is limited and locks are better released sooner than later.

I'm running an online workshop on the 20-21 and 23-24 of November about High-Performance Java Persistence.

If you enjoyed this article, I bet you are going to love my Book and Video Courses as well.

Conclusion

The after_transaction connection release mode is more efficient than the default JTA after_statement strategy, and so it should be used if the JTA transaction resource management logic doesn’t interfere with this connection releasing strategy.

Transactions and Concurrency Control eBook

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.