Skip to content

Commit 8d83f69

Browse files
committed
Hibernate synchronization properly unbinds Session even in case of afterCompletion exception (SPR-8757)
1 parent ce5117c commit 8d83f69

File tree

1 file changed

+32
-24
lines changed

1 file changed

+32
-24
lines changed

org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SpringSessionSynchronization.java

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2011 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -218,32 +218,40 @@ public void afterCommit() {
218218
}
219219

220220
public void afterCompletion(int status) {
221-
if (!this.hibernateTransactionCompletion || !this.newSession) {
222-
// No Hibernate TransactionManagerLookup: apply afterTransactionCompletion callback.
223-
// Always perform explicit afterTransactionCompletion callback for pre-bound Session,
224-
// even with Hibernate TransactionManagerLookup (which only applies to new Sessions).
225-
Session session = this.sessionHolder.getSession();
226-
// Provide correct transaction status for releasing the Session's cache locks,
227-
// if possible. Else, closing will release all cache locks assuming a rollback.
228-
if (session instanceof SessionImplementor) {
229-
((SessionImplementor) session).afterTransactionCompletion(status == STATUS_COMMITTED, null);
230-
}
231-
// Close the Hibernate Session here if necessary
232-
// (closed in beforeCompletion in case of TransactionManagerLookup).
233-
if (this.newSession) {
234-
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, this.sessionFactory);
221+
try {
222+
if (!this.hibernateTransactionCompletion || !this.newSession) {
223+
// No Hibernate TransactionManagerLookup: apply afterTransactionCompletion callback.
224+
// Always perform explicit afterTransactionCompletion callback for pre-bound Session,
225+
// even with Hibernate TransactionManagerLookup (which only applies to new Sessions).
226+
Session session = this.sessionHolder.getSession();
227+
// Provide correct transaction status for releasing the Session's cache locks,
228+
// if possible. Else, closing will release all cache locks assuming a rollback.
229+
try {
230+
if (session instanceof SessionImplementor) {
231+
((SessionImplementor) session).afterTransactionCompletion(status == STATUS_COMMITTED, null);
232+
}
233+
}
234+
finally {
235+
// Close the Hibernate Session here if necessary
236+
// (closed in beforeCompletion in case of TransactionManagerLookup).
237+
if (this.newSession) {
238+
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, this.sessionFactory);
239+
}
240+
else if (!this.hibernateTransactionCompletion) {
241+
session.disconnect();
242+
}
243+
}
235244
}
236-
else if (!this.hibernateTransactionCompletion) {
237-
session.disconnect();
245+
if (!this.newSession && status != STATUS_COMMITTED) {
246+
// Clear all pending inserts/updates/deletes in the Session.
247+
// Necessary for pre-bound Sessions, to avoid inconsistent state.
248+
this.sessionHolder.getSession().clear();
238249
}
239250
}
240-
if (!this.newSession && status != STATUS_COMMITTED) {
241-
// Clear all pending inserts/updates/deletes in the Session.
242-
// Necessary for pre-bound Sessions, to avoid inconsistent state.
243-
this.sessionHolder.getSession().clear();
244-
}
245-
if (this.sessionHolder.doesNotHoldNonDefaultSession()) {
246-
this.sessionHolder.setSynchronizedWithTransaction(false);
251+
finally {
252+
if (this.sessionHolder.doesNotHoldNonDefaultSession()) {
253+
this.sessionHolder.setSynchronizedWithTransaction(false);
254+
}
247255
}
248256
}
249257

0 commit comments

Comments
 (0)