Skip to content

Commit c024bdc

Browse files
committed
Cleanup after unexpected exception from external delegation call
Issue: SPR-17559
1 parent 6d7827e commit c024bdc

File tree

2 files changed

+41
-27
lines changed

2 files changed

+41
-27
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,21 +115,28 @@ public static Connection doGetConnection(DataSource dataSource) throws SQLExcept
115115
Connection con = fetchConnection(dataSource);
116116

117117
if (TransactionSynchronizationManager.isSynchronizationActive()) {
118-
// Use same Connection for further JDBC actions within the transaction.
119-
// Thread-bound object will get removed by synchronization at transaction completion.
120-
ConnectionHolder holderToUse = conHolder;
121-
if (holderToUse == null) {
122-
holderToUse = new ConnectionHolder(con);
123-
}
124-
else {
125-
holderToUse.setConnection(con);
118+
try {
119+
// Use same Connection for further JDBC actions within the transaction.
120+
// Thread-bound object will get removed by synchronization at transaction completion.
121+
ConnectionHolder holderToUse = conHolder;
122+
if (holderToUse == null) {
123+
holderToUse = new ConnectionHolder(con);
124+
}
125+
else {
126+
holderToUse.setConnection(con);
127+
}
128+
holderToUse.requested();
129+
TransactionSynchronizationManager.registerSynchronization(
130+
new ConnectionSynchronization(holderToUse, dataSource));
131+
holderToUse.setSynchronizedWithTransaction(true);
132+
if (holderToUse != conHolder) {
133+
TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
134+
}
126135
}
127-
holderToUse.requested();
128-
TransactionSynchronizationManager.registerSynchronization(
129-
new ConnectionSynchronization(holderToUse, dataSource));
130-
holderToUse.setSynchronizedWithTransaction(true);
131-
if (holderToUse != conHolder) {
132-
TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
136+
catch (RuntimeException ex) {
137+
// Unexpected exception from external delegation call -> close Connection and rethrow.
138+
releaseConnection(con, dataSource);
139+
throw ex;
133140
}
134141
}
135142

spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -266,21 +266,28 @@ else if (!TransactionSynchronizationManager.isSynchronizationActive()) {
266266
em = (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties) : emf.createEntityManager());
267267
}
268268

269-
// Use same EntityManager for further JPA operations within the transaction.
270-
// Thread-bound object will get removed by synchronization at transaction completion.
271-
emHolder = new EntityManagerHolder(em);
272-
if (synchronizedWithTransaction) {
273-
Object transactionData = prepareTransaction(em, emf);
274-
TransactionSynchronizationManager.registerSynchronization(
275-
new TransactionalEntityManagerSynchronization(emHolder, emf, transactionData, true));
276-
emHolder.setSynchronizedWithTransaction(true);
269+
try {
270+
// Use same EntityManager for further JPA operations within the transaction.
271+
// Thread-bound object will get removed by synchronization at transaction completion.
272+
emHolder = new EntityManagerHolder(em);
273+
if (synchronizedWithTransaction) {
274+
Object transactionData = prepareTransaction(em, emf);
275+
TransactionSynchronizationManager.registerSynchronization(
276+
new TransactionalEntityManagerSynchronization(emHolder, emf, transactionData, true));
277+
emHolder.setSynchronizedWithTransaction(true);
278+
}
279+
else {
280+
// Unsynchronized - just scope it for the transaction, as demanded by the JPA 2.1 spec...
281+
TransactionSynchronizationManager.registerSynchronization(
282+
new TransactionScopedEntityManagerSynchronization(emHolder, emf));
283+
}
284+
TransactionSynchronizationManager.bindResource(emf, emHolder);
277285
}
278-
else {
279-
// Unsynchronized - just scope it for the transaction, as demanded by the JPA 2.1 spec...
280-
TransactionSynchronizationManager.registerSynchronization(
281-
new TransactionScopedEntityManagerSynchronization(emHolder, emf));
286+
catch (RuntimeException ex) {
287+
// Unexpected exception from external delegation call -> close EntityManager and rethrow.
288+
closeEntityManager(em);
289+
throw ex;
282290
}
283-
TransactionSynchronizationManager.bindResource(emf, emHolder);
284291

285292
return em;
286293
}

0 commit comments

Comments
 (0)