当外部事务标记为回滚时,回滚所有嵌套事务

时间:2012-06-25 17:00:34

标签: java spring transactions rollback propagation

我有两个用@Transactional注释的方法。第二种方法被称为嵌套在第一种方法中。

现在我希望发生以下行为:

  • 每次输入第二个嵌套方法时,都会嵌入一个新的嵌套方法 应该创建交易。当该交易被标记为a时 回滚,只应该回滚该事务。
  • 但是当 外部方法的事务被标记为每次回滚 嵌套事务内部 - 是否标记为回滚 - 应该回滚。

如何设置Propagation值以实现此类功能?


P上。 S。:我正在使用HibernateTransactionManager

3 个答案:

答案 0 :(得分:3)

您需要使用NESTED。请注意,此传播模式使用JDBC SavePoints来实现此行为,因此嵌套行为仅在事务只是JDBC连接的包装时才起作用。它不适用于JTA交易。有关详细信息,请参阅Spring documentation

答案 1 :(得分:1)

应该澄清Java Transactions中的默认行为。除非父提交,否则所有嵌套事务都不会提交。在此处阅读http://en.wikibooks.org/wiki/Java_Persistence/Transactions

答案 2 :(得分:0)

我建议在单独的线程中实现这样的功能,即您希望在嵌套事务中启动的方法 - 只需在单独的线程中启动它们。它可能看起来像伪代码:

//SomeService 
// Here we start an external transaction
@Transactional
    int processAllInTransaction() {
        List<Integer> jobIds = jobService.getJobs();
        if (!jobIds.isEmpty()) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    jobIds.forEach(jobId ->
                            //Execute eveything in external transaction   
                            threadPool.execute(jobId)
                    );
                }
            }).start();

        } 
        return jobIds.size();
    }

//Method of Executor Service
void execute(final int jobId) {
    tasks.add(taskExecutor.submit(new Runnable() {
        void run() {
            someProcessor.processJob(jobId);
        }
    }));
}

//Method of another Service
@Transactional
public void processJob(int jobId) {
    //this will work in separate thransaction since was executed in another Theread
    someDao.doWorkInExternalTransaction(jobId);
}

如果你真的需要控制外部事务 - 嵌套事务在新的Theread中的单个外部事务中工作,只需等待Thread返回的结果并在需要时抛出异常