在多线程进程中运行存储过程

时间:2015-09-27 23:33:00

标签: java multithreading spring hibernate jta

我有这种方法迭代列表并调用存储过程。它工作正常。

@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。

1 个答案:

答案 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中包装存储过程调用。