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,32 +218,40 @@ class SpringSessionSynchronization implements TransactionSynchronization, Ordere
} }
public void afterCompletion(int status) { public void afterCompletion(int status) {
if (!this.hibernateTransactionCompletion || !this.newSession) { try {
// No Hibernate TransactionManagerLookup: apply afterTransactionCompletion callback. if (!this.hibernateTransactionCompletion || !this.newSession) {
// Always perform explicit afterTransactionCompletion callback for pre-bound Session, // No Hibernate TransactionManagerLookup: apply afterTransactionCompletion callback.
// even with Hibernate TransactionManagerLookup (which only applies to new Sessions). // Always perform explicit afterTransactionCompletion callback for pre-bound Session,
Session session = this.sessionHolder.getSession(); // even with Hibernate TransactionManagerLookup (which only applies to new Sessions).
// Provide correct transaction status for releasing the Session's cache locks, Session session = this.sessionHolder.getSession();
// if possible. Else, closing will release all cache locks assuming a rollback. // Provide correct transaction status for releasing the Session's cache locks,
if (session instanceof SessionImplementor) { // if possible. Else, closing will release all cache locks assuming a rollback.
((SessionImplementor) session).afterTransactionCompletion(status == STATUS_COMMITTED, null); try {
if (session instanceof SessionImplementor) {
((SessionImplementor) session).afterTransactionCompletion(status == STATUS_COMMITTED, null);
}
}
finally {
// Close the Hibernate Session here if necessary
// (closed in beforeCompletion in case of TransactionManagerLookup).
if (this.newSession) {
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, this.sessionFactory);
}
else if (!this.hibernateTransactionCompletion) {
session.disconnect();
}
}
} }
// Close the Hibernate Session here if necessary if (!this.newSession && status != STATUS_COMMITTED) {
// (closed in beforeCompletion in case of TransactionManagerLookup). // Clear all pending inserts/updates/deletes in the Session.
if (this.newSession) { // Necessary for pre-bound Sessions, to avoid inconsistent state.
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, this.sessionFactory); this.sessionHolder.getSession().clear();
}
else if (!this.hibernateTransactionCompletion) {
session.disconnect();
} }
} }
if (!this.newSession && status != STATUS_COMMITTED) { finally {
// Clear all pending inserts/updates/deletes in the Session. if (this.sessionHolder.doesNotHoldNonDefaultSession()) {
// Necessary for pre-bound Sessions, to avoid inconsistent state. this.sessionHolder.setSynchronizedWithTransaction(false);
this.sessionHolder.getSession().clear(); }
}
if (this.sessionHolder.doesNotHoldNonDefaultSession()) {
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) {
if (status != STATUS_COMMITTED) { try {
// Clear all pending inserts/updates/deletes in the Session. if (status != STATUS_COMMITTED) {
// Necessary for pre-bound Sessions, to avoid inconsistent state. // Clear all pending inserts/updates/deletes in the Session.
this.sessionHolder.getSession().clear(); // Necessary for pre-bound Sessions, to avoid inconsistent state.
this.sessionHolder.getSession().clear();
}
}
finally {
this.sessionHolder.setSynchronizedWithTransaction(false);
} }
this.sessionHolder.setSynchronizedWithTransaction(false);
} }
} }