Why you should always use hibernate.connection.provider_disables_autocommit for resource-local JPA transactions

Introduction

One of my major goals for Hibernate is to make sure we offer all sorts of performance improvements to reduce transaction response time and increase throughput. In Hibernate 5.2.10, we addressed the HHH-11542 Jira issue which allows you now to delay the database connection acquisition for resource-local transactions as well.

In this article, I’m going to explain how Hibernate acquires connections and why you want it to delay this process as long as possible.

Resource-local vs. JTA

In Hibernate, the database connection acquisition, as well as the connection release, are relative to the type of the currently running transaction:

  • resource-local: For JDBC transactions, that operate with a single DataSource, the Connection is acquired right when the transaction starts and is closed when the transaction ends (either commit or roll back)
  • JTA: For XA transactions, that span over multiple DataSource(s), the Connection is acquired upon executing the first Statement and is released after each Statement execution. The aggressive connection release mechanism can be skipped if the underlying application server allows us to do so.

Delaying the resource-local connectcion acquisition

Our goal is to make the resource-local transaction behave like JTA and delay the connection acquisition until Hibernate needs to execute the first JDBC Statement of the currently running unit-of-work.

The reason why resource-local transaction requires a database connection from the very beginning can be easily visualized in the following diagram:

Hibernate needs to check the underlying JDBC Connection auto-commit status, and disable it if the Connection is set to auto-commit. This way, Hibernate can control the transaction boundaries and make sure that the unit-of-work JDBC Statement(s) are executed in the context of the same database transaction.

Although this behavior is correct since we cannot know if the auto-commit flag was set or not, we could hint Hibernate to skip this check since we already know that all JDBC Connection(s) run in manual commit mode.

For instance, all enterprise applications already use a connection pooling solution which can disable the auto-commit mode when the database connection is firsts established.

HikariConfig hikariConfig = super.hikariConfig( dataSource );
hikariConfig.setAutoCommit( false );

For this reason, in Hibernate 5.2.10, we introduced the hibernate.connection.provider_disables_autocommit configuration property which tells Hibernate that the underlying JDBC Connection(s) already disabled the auto-commit mode.

Benchmark

To measure the performance advantage of delaying database connection acquisition, we are going to use a test case which emulates a resource intensive XML document parsing which happens within the boundaries of the JPA transaction context.

If we don’t delay the connection acquisition, the XML parsing duration is going to be added to the database connection lease time. However, once we switch to the new connection delay mechanism, the connection lease time is reduced considerably as illustrated by the graph below.

Therefore, if you are using resource-local transactions (which is quite the norm when using Spring framework), you should definitely configure the connection pool (e.g. HikariCP) to disable the auto-commit commit, and provide the connection acquisition delay Hibernate configuration property:

<property 
    name="hibernate.connection.provider_disables_autocommit"
    value="true"
/>

If you enjoyed this article, I bet you are going to love my book as well.

Conclusion

Hibernate is not just an ORM tool, but a full-blown data access framework. Because database connection management is very important for a high-performance enterprise application, Hibernate allows you to minimize the window of time required to execute a database transaction which leads to a higher transaction throughput as well.

Enter your email address to follow this blog and receive notifications of new posts by email.

Advertisements

12 thoughts on “Why you should always use hibernate.connection.provider_disables_autocommit for resource-local JPA transactions

  1. Great tip, Vlad!

    Delaying the connection acquisition may improve a lot the performance in many situations!

    Thanks for this new post!

    1. Resource-local implies a single DataSource and the transaction is coordinated at the JDBC Connection level. JTA implies multiple sources of data, be them DataSource or a JMS queue. The JTA transaction is coordinated by an XA transaction manager. Although this is a very complex topic, you can find many explanations about it in my book.

  2. If I enable this functionality in my Spring Boot project (I imagine this isn’t Spring Boot specific) with Hibernate 5.2.10 using application.properties entries of:
    spring.jpa.properties.hibernate.connection.provider_disables_autocommit=true
    spring.datasource.tomcat.default-auto-commit=false
    spring.datasource.hikari.auto-commit=false
    spring.datasource.dbcp2.default-auto-commit=false

    And run my integration tests against H2 (this problem does not occur when running against Postgres), I get this error:
    org.h2.jdbc.JdbcSQLException: Table “HT_ABSTRACT_PANEL_DESCRIPTION” not found

    https://hibernate.atlassian.net/browse/HHH-11262 sounds potentially related, but I’m otherwise using all Hibernate and Spring Boot defaults (ex, hibernate.hql.bulk_id_strategy is not set).

    Is there some reason provider_disables_autocommit would trigger this erroneous behavior?

  3. Hi, when I enable the hibernate.connection.provider_disables_autocommit property to true, all my tests fails, telling me that there’re some constraints violation on an entity.

    I use the @Transactional and @Rollback annotations that comes from Spring and in the @Before method I create an entity that have an unique constraint on the email field.

    Basically seems to be that the @Rollback annotation stop working when the hibernate.connection.provider_disables_autocommit property is set to true.

    In the tests I’m using HSQL as an in-memory database

    1. As long as you set the CP to disable auto-commit, there shouldn’t be any problem. If you didn’t do so, I would no be surprised to see all sorts of weird side-effects.

  4. Hi Vlad,
    I want to ask you what is the difference between “hibernate.connection.autocommit” and the new one “hibernate.connection.provider_disables_autocommit”?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s