diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java index e7f0713aaf..312df866fc 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java @@ -115,21 +115,28 @@ public abstract class DataSourceUtils { Connection con = fetchConnection(dataSource); if (TransactionSynchronizationManager.isSynchronizationActive()) { - // Use same Connection for further JDBC actions within the transaction. - // Thread-bound object will get removed by synchronization at transaction completion. - ConnectionHolder holderToUse = conHolder; - if (holderToUse == null) { - holderToUse = new ConnectionHolder(con); + try { + // Use same Connection for further JDBC actions within the transaction. + // Thread-bound object will get removed by synchronization at transaction completion. + ConnectionHolder holderToUse = conHolder; + if (holderToUse == null) { + holderToUse = new ConnectionHolder(con); + } + else { + holderToUse.setConnection(con); + } + holderToUse.requested(); + TransactionSynchronizationManager.registerSynchronization( + new ConnectionSynchronization(holderToUse, dataSource)); + holderToUse.setSynchronizedWithTransaction(true); + if (holderToUse != conHolder) { + TransactionSynchronizationManager.bindResource(dataSource, holderToUse); + } } - else { - holderToUse.setConnection(con); - } - holderToUse.requested(); - TransactionSynchronizationManager.registerSynchronization( - new ConnectionSynchronization(holderToUse, dataSource)); - holderToUse.setSynchronizedWithTransaction(true); - if (holderToUse != conHolder) { - TransactionSynchronizationManager.bindResource(dataSource, holderToUse); + catch (RuntimeException ex) { + // Unexpected exception from external delegation call -> close Connection and rethrow. + releaseConnection(con, dataSource); + throw ex; } } diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java b/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java index a6fa99c6bc..d6e8638b66 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java @@ -266,21 +266,28 @@ public abstract class EntityManagerFactoryUtils { em = (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager()); } - // Use same EntityManager for further JPA operations within the transaction. - // Thread-bound object will get removed by synchronization at transaction completion. - emHolder = new EntityManagerHolder(em); - if (synchronizedWithTransaction) { - Object transactionData = prepareTransaction(em, emf); - TransactionSynchronizationManager.registerSynchronization( - new TransactionalEntityManagerSynchronization(emHolder, emf, transactionData, true)); - emHolder.setSynchronizedWithTransaction(true); + try { + // Use same EntityManager for further JPA operations within the transaction. + // Thread-bound object will get removed by synchronization at transaction completion. + emHolder = new EntityManagerHolder(em); + if (synchronizedWithTransaction) { + Object transactionData = prepareTransaction(em, emf); + TransactionSynchronizationManager.registerSynchronization( + new TransactionalEntityManagerSynchronization(emHolder, emf, transactionData, true)); + emHolder.setSynchronizedWithTransaction(true); + } + else { + // Unsynchronized - just scope it for the transaction, as demanded by the JPA 2.1 spec... + TransactionSynchronizationManager.registerSynchronization( + new TransactionScopedEntityManagerSynchronization(emHolder, emf)); + } + TransactionSynchronizationManager.bindResource(emf, emHolder); } - else { - // Unsynchronized - just scope it for the transaction, as demanded by the JPA 2.1 spec... - TransactionSynchronizationManager.registerSynchronization( - new TransactionScopedEntityManagerSynchronization(emHolder, emf)); + catch (RuntimeException ex) { + // Unexpected exception from external delegation call -> close EntityManager and rethrow. + closeEntityManager(em); + throw ex; } - TransactionSynchronizationManager.bindResource(emf, emHolder); return em; }