我有这种方法迭代列表并调用存储过程。它工作正常。
@Transactional(propagation = Propagation.SUPPORTS)
public class SomeService{
@Autowired
MyJpaConfiguration myJpaConfiguration ;
private String runProcedure(...){
for (int j = 0; j < size; j++) {
EntityManager entityManager = myJpaConfiguration.mainUnitEM();
Query query = entityManager.createNativeQuery("CALL PROCEDURE(params...)");
query.setParameter(...);
query.executeUpdate();
}
}
}
现在,为了加快这个过程,我想做同样的事情但是并行调用,所以我的代码变成了
@Transactional(propagation = Propagation.SUPPORTS)
public class SomeService{
@Autowired
MyJpaConfiguration myJpaConfiguration ;
private String runProcedure(...){
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
for (int j = 0; j < size; j++) {
executor.submit(new Callable<String>(){
public String call() throws Exception {
EntityManager entityManager = myJpaConfiguration.mainUnitEM();
Query query = entityManager.createNativeQuery("CALL PROCEDURE(params...)");
query.setParameter(...);
query.executeUpdate();
return "Ok";
}
});
}
}
}
我的问题是当并行运行这段代码时,我收到了这个错误:
javax.persistence.TransactionRequiredException: Executing an update/delete query
我理解由于某种原因新线程找不到当前的事务上下文,所以我尝试通过
手动启动事务 entityManager.getTransaction().begin();
...
entityManager.getTransaction().commit();
但我得到
A JTA EntityManager cannot use getTransaction()
因为它是一个容器管理的交易而产生感觉。
此时,我只是不知道如何在多线程环境中管理事务。
我使用Spring3.2,Hibernate 3.6,atomikos 3.8 for JTA。
答案 0 :(得分:1)
您可以使用TransactionTemplate(请参阅the example)
@Autowired
private TransactionTemplate txTemplate;
/**
* Insert new user using transactionTemplate.
* @param user
*/
public void insertUserByTxTemplate(final User user) {
txTemplate.execute(new TransactionCallback() {
@Override
public Void doInTransaction(TransactionStatus txStatus) {
try {
Session session = sessionFactory.getCurrentSession();
session.save(user);
throw new RuntimeException("Exception throwed!");
} catch (Exception e) {
txStatus.setRollbackOnly();
}
return null;
}
});
}
您可以在TransactionCallback中包装存储过程调用。