Hibernate synchronization properly unbinds Session even in case of afterCompletion exception (SPR-8757)

This commit is contained in:
Juergen Hoeller 2011-12-22 02:51:13 +01:00 committed by Chris Beams
parent 09ac195f0c
commit 07ddedd7bf
2 changed files with 41 additions and 29 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2011 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -218,6 +218,7 @@ class SpringSessionSynchronization implements TransactionSynchronization, Ordere
} }
public void afterCompletion(int status) { public void afterCompletion(int status) {
try {
if (!this.hibernateTransactionCompletion || !this.newSession) { if (!this.hibernateTransactionCompletion || !this.newSession) {
// No Hibernate TransactionManagerLookup: apply afterTransactionCompletion callback. // No Hibernate TransactionManagerLookup: apply afterTransactionCompletion callback.
// Always perform explicit afterTransactionCompletion callback for pre-bound Session, // Always perform explicit afterTransactionCompletion callback for pre-bound Session,
@ -225,9 +226,12 @@ class SpringSessionSynchronization implements TransactionSynchronization, Ordere
Session session = this.sessionHolder.getSession(); Session session = this.sessionHolder.getSession();
// Provide correct transaction status for releasing the Session's cache locks, // Provide correct transaction status for releasing the Session's cache locks,
// if possible. Else, closing will release all cache locks assuming a rollback. // if possible. Else, closing will release all cache locks assuming a rollback.
try {
if (session instanceof SessionImplementor) { if (session instanceof SessionImplementor) {
((SessionImplementor) session).afterTransactionCompletion(status == STATUS_COMMITTED, null); ((SessionImplementor) session).afterTransactionCompletion(status == STATUS_COMMITTED, null);
} }
}
finally {
// Close the Hibernate Session here if necessary // Close the Hibernate Session here if necessary
// (closed in beforeCompletion in case of TransactionManagerLookup). // (closed in beforeCompletion in case of TransactionManagerLookup).
if (this.newSession) { if (this.newSession) {
@ -237,14 +241,18 @@ class SpringSessionSynchronization implements TransactionSynchronization, Ordere
session.disconnect(); session.disconnect();
} }
} }
}
if (!this.newSession && status != STATUS_COMMITTED) { if (!this.newSession && status != STATUS_COMMITTED) {
// Clear all pending inserts/updates/deletes in the Session. // Clear all pending inserts/updates/deletes in the Session.
// Necessary for pre-bound Sessions, to avoid inconsistent state. // Necessary for pre-bound Sessions, to avoid inconsistent state.
this.sessionHolder.getSession().clear(); this.sessionHolder.getSession().clear();
} }
}
finally {
if (this.sessionHolder.doesNotHoldNonDefaultSession()) { if (this.sessionHolder.doesNotHoldNonDefaultSession()) {
this.sessionHolder.setSynchronizedWithTransaction(false); this.sessionHolder.setSynchronizedWithTransaction(false);
} }
} }
}
} }

View File

@ -111,12 +111,16 @@ class SpringSessionSynchronization implements TransactionSynchronization, Ordere
} }
public void afterCompletion(int status) { public void afterCompletion(int status) {
try {
if (status != STATUS_COMMITTED) { if (status != STATUS_COMMITTED) {
// Clear all pending inserts/updates/deletes in the Session. // Clear all pending inserts/updates/deletes in the Session.
// Necessary for pre-bound Sessions, to avoid inconsistent state. // Necessary for pre-bound Sessions, to avoid inconsistent state.
this.sessionHolder.getSession().clear(); this.sessionHolder.getSession().clear();
} }
}
finally {
this.sessionHolder.setSynchronizedWithTransaction(false); this.sessionHolder.setSynchronizedWithTransaction(false);
} }
}
} }