It’s not complicated at all.
-
First, you need to understand that the Spring transaction manager is only a transaction management abstraction. In your case, the actual transactions happen at the JDBC Connection level.
-
All
@Transactionalservice method calls are intercepted by theTransactionInterceptorAspect. -
The
TransactionIntreceptordelegates transaction management to the current configured
AbstractPlatformTransactionManagerimplementation (JpaTransactionManagerin your case). -
JpaTransactionManagerwill bind the current running Spring transaction to an EntityManager, so all DAOs participating in the current transaction share the same Persistence Context. -
JpaTransactionManagersimply uses theEntityManagerTransaction API for controlling transactions:EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction(); tx.commit();
The JPA Transaction API simply delegates the call to the underlying JDBC Connection commit/rollback methods.
-
When the transaction is done (commit/rollback), the
org.hibernate.engine.transaction.internal.jdbc.JdbcTransactioncalls:transactionCoordinator().getTransactionContext().managedClose();
which triggers a Hibernate Session (Entity Manager) close.
-
The underlying JDBC connection is therefore triggered to be closed as well:
jdbcCoordinator.close(); -
Hibernate has a logical JDBC connection handle:
@Override public Connection close() { LOG.tracev( "Closing JDBC container [{0}]", this ); if ( currentBatch != null ) { LOG.closingUnreleasedBatch(); currentBatch.release(); } cleanup(); return logicalConnection.close(); } -
The logical connection delegates the close call to the currently configured connection provider (
DataSourceConnectionProviderin your case), which simply calls the close method on the JDBC connection:@Override public void closeConnection(Connection connection) throws SQLException { connection.close(); } -
Like any other connection pooling DataSource, the JDBC connection close simply returns the connection to the pool and doesn’t close the physical database connection. That’s because the connection pooling DataSource returns a JDBC Connection proxy that intercepts all calls and delegates the closing to the connection pool handling logic.
Note that for RESOURCE_LOCAL transactions, you should also set the hibernate.connection.provider_disables_autocommit property if the autocommit check was disabled by the connection pool. This way, the database connections are going to be acquired lazily prior to executing a SQL query or flushing the Persistence Context.