@@ -239,17 +239,14 @@ public void resume() {
239
239
*/
240
240
@ Override
241
241
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 ()) {
248
245
try {
249
246
if (logger .isDebugEnabled ()) {
250
- logger .debug ("Transaction synchronization committing SqlSession [" + this .holder .getSqlSession () + "]" );
247
+ logger .debug ("Transaction synchronization flushing SqlSession [" + this .holder .getSqlSession () + "]" );
251
248
}
252
- this .holder .getSqlSession ().commit ();
249
+ this .holder .getSqlSession ().flushStatements ();
253
250
} catch (PersistenceException p ) {
254
251
if (this .holder .getPersistenceExceptionTranslator () != null ) {
255
252
DataAccessException translated = this .holder .getPersistenceExceptionTranslator ().translateExceptionIfPossible (p );
@@ -267,19 +264,43 @@ public void beforeCommit(boolean readOnly) {
267
264
*/
268
265
@ Override
269
266
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 ();
279
303
}
280
- this .holder .getSqlSession ().close ();
281
- } finally {
282
- this .holder .reset ();
283
304
}
284
305
}
285
306
}
0 commit comments