Skip to content

Commit 7207775

Browse files
committed
fix for http://code.google.com/p/mybatis/issues/detail?id=553 : 2nd level cache consistency with MyBatis-Spring
1 parent fd5aaee commit 7207775

File tree

2 files changed

+60
-20
lines changed

2 files changed

+60
-20
lines changed

src/main/java/org/mybatis/spring/SqlSessionUtils.java

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -239,17 +239,14 @@ public void resume() {
239239
*/
240240
@Override
241241
public void beforeCommit(boolean readOnly) {
242-
// Connection commit or rollback will be handled by ConnectionSynchronization or
243-
// DataSourceTransactionManager.
244-
// But, do cleanup the SqlSession / Executor, including flushing BATCH statements so
245-
// they are actually executed.
246-
// SpringManagedTransaction will no-op the commit over the jdbc connection
247-
if (isActualTransactionActive()) {
242+
// Flush BATCH statements so they are actually executed before the connection is committed.
243+
// If there is no tx active data will be rolled back so there is no need to flush batches
244+
if (this.holder.getExecutorType() == ExecutorType.BATCH && isActualTransactionActive()) {
248245
try {
249246
if (logger.isDebugEnabled()) {
250-
logger.debug("Transaction synchronization committing SqlSession [" + this.holder.getSqlSession() + "]");
247+
logger.debug("Transaction synchronization flushing SqlSession [" + this.holder.getSqlSession() + "]");
251248
}
252-
this.holder.getSqlSession().commit();
249+
this.holder.getSqlSession().flushStatements();
253250
} catch (PersistenceException p) {
254251
if (this.holder.getPersistenceExceptionTranslator() != null) {
255252
DataAccessException translated = this.holder.getPersistenceExceptionTranslator().translateExceptionIfPossible(p);
@@ -267,19 +264,43 @@ public void beforeCommit(boolean readOnly) {
267264
*/
268265
@Override
269266
public void afterCompletion(int status) {
270-
// unbind the SqlSession from tx synchronization
271-
// Note, assuming DefaultSqlSession, rollback is not needed because rollback on
272-
// SpringManagedTransaction will no-op anyway. In addition, closing the session cleans
273-
// up the same internal resources as rollback.
274-
if (!this.holder.isOpen()) {
275-
unbindResource(this.sessionFactory);
276-
try {
277-
if (logger.isDebugEnabled()) {
278-
logger.debug("Transaction synchronization closing SqlSession [" + this.holder.getSqlSession() + "]");
267+
// Unbind the SqlSession from tx synchronization
268+
// Note, commit/rollback is needed to ensure 2nd level cache is properly updated
269+
// SpringTransaction will no-op the connection commit/rollback
270+
try {
271+
// Do not call commit unless there is really a transaction;
272+
// no need to commit if just tx synchronization is active but no transaction was started
273+
if (isActualTransactionActive()) {
274+
switch (status) {
275+
case STATUS_COMMITTED:
276+
if (logger.isDebugEnabled()) {
277+
logger.debug("Transaction synchronization committing SqlSession [" + this.holder.getSqlSession() + "]");
278+
}
279+
holder.getSqlSession().commit();
280+
break;
281+
case STATUS_ROLLED_BACK:
282+
if (logger.isDebugEnabled()) {
283+
logger.debug("Transaction synchronization rolling back SqlSession [" + this.holder.getSqlSession() + "]");
284+
}
285+
holder.getSqlSession().rollback();
286+
break;
287+
default:
288+
if (logger.isDebugEnabled()) {
289+
logger.debug("Transaction synchronization ended with unknown status for SqlSession [" + this.holder.getSqlSession() + "]");
290+
}
291+
}
292+
}
293+
} finally {
294+
if (!holder.isOpen()) {
295+
unbindResource(sessionFactory);
296+
try {
297+
if (logger.isDebugEnabled()) {
298+
logger.debug("Transaction synchronization closing SqlSession [" + this.holder.getSqlSession() + "]");
299+
}
300+
this.holder.getSqlSession().close();
301+
} finally {
302+
this.holder.reset();
279303
}
280-
this.holder.getSqlSession().close();
281-
} finally {
282-
this.holder.reset();
283304
}
284305
}
285306
}

src/test/java/org/mybatis/spring/MyBatisSpringTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,25 @@ public void testWithTxSupports() {
361361
assertSingleConnection();
362362
}
363363

364+
365+
@Test
366+
public void testRollbackWithTxSupports() {
367+
DefaultTransactionDefinition txDef = new DefaultTransactionDefinition();
368+
txDef.setPropagationBehaviorName("PROPAGATION_SUPPORTS");
369+
370+
TransactionStatus status = txManager.getTransaction(txDef);
371+
372+
session = SqlSessionUtils.getSqlSession(sqlSessionFactory);
373+
session.getMapper(TestMapper.class).findTest();
374+
SqlSessionUtils.closeSqlSession(session, sqlSessionFactory);
375+
376+
txManager.rollback(status);
377+
378+
// SUPPORTS should just activate tx synchronization but not commits
379+
assertNoCommit();
380+
assertSingleConnection();
381+
}
382+
364383
@Test
365384
public void testWithTxRequired() {
366385
DefaultTransactionDefinition txDef = new DefaultTransactionDefinition();

0 commit comments

Comments
 (0)