Search code examples
javaspringmybatisspring-mybatis

Using Spring Transaction with Mybatis batch


I have a @Transactional method which invokes another method on a common spring bean, that has long been used to perform batch operations, across mappers. The problem now is that, if there is an error in the @Transactional method, the DMLs executed on the batch are not rolled back, as they were executed on a different session, with it's own transaction.

public class HamsterRepo{
...

 @Autowired 
 BatchOperationBean<Hamsters> idioticBatchBean;
 @Transactional
 public void saveHamsters(List<Hamsters> hams){
  idioticBatchBean.executebatch("saveHamsters", hams);
 }
}
 public class BatchOperationBean<T>{
 @Autowired 
 SqlSessionFactory sqlFactory; 

 public void executebatch(String mapperId, List<T> ts){
  SqlSession sqlSession = 
  this.sqlSessionFactory.openSession(ExecutorType.BATCH,
                TransactionIsolationLevel.SERIALIZABLE); 
  try(sqlSession){
   for(T t in ts){
    sqlSession.update(mapperId , t);
   }
  sqlSession.commit();
  // Clean Up stuff and Exception Handling...
  }
 }
}

Now, Is there a way to relate the two Spring Tx and SqlSessionFactory? Will injecting SqlSession, instead of the factory help? Or is there a way to obtain the SqlSession from Spring Tx? Or a way in Spring to identify & execute queries across mappers without an SqlSesion?

PS: Using Spring 4.1.7, Mybatis: 3.4.4, Mybatis-spring : 1.3.1


Solution

  • Looks like the the way to link Spring Transaction and Mybatis SqlSession is the SqlSessionTemplate

    Thread safe, Spring managed, SqlSession that works with Spring transaction management to ensure that that the actual SqlSession used is the one associated with the current Spring transaction. In addition, it manages the session life-cycle, including closing, committing or rolling back the session as necessary based on the Spring transaction configuration.