使用@Transactional注释的问题

时间:2010-03-05 05:48:15

标签: java spring transactions rollback

我正在尝试使用Spring提供的声明式事务管理功能。我已经按照参考文档(即包括AOP,tx命名空间和使用<tx:annotation-driven />标记)中的描述设置了弹簧配置和bean,并在我希望成为事务的方法上使用@Transactional注释。

这就是代码的样子:

public interface Worker {
    public workOnEvents(List<Events> eventsForACustomer);
}

public class WorkerImpl {
    @Transactional
    public workOnEvents(List<Events> eventsForACustomer) {
        for(Event event : eventsForACustomer) {
            // get DAO's based on event types at runtime,
            // so we will have different DAO's acting within this loop
            DAOFactory.getDAO(event.getType()).persistEvent(event);
        }
    }
}

现在,我希望如果上面循环中的任何DAO都无法处理该事件,那么应该回滚在此循环之前循环中的其他DAO对数据库所做的所有更改。

因此,为了测试回滚,我列出了一些事件说(e1,e2,e3),这些事件会导致DAO接收(d1,d2,d3),然后我故意在运行中抛出一个运行时异常。 DAO d2的persistEvent方法。但是,我得到的结果是程序终止而不继续循环中的事件e3,而不是处理抛出的异常。此外,DAO d1保留的数据不会回滚。

请让我知道我在这里可能做错了什么?

4 个答案:

答案 0 :(得分:1)

您对应该发生的事情的期望不会得到注释方法的满足。它的工作方式是注释将方法标记为Spring应用建议的方法,并且通知包装方法,因此可以在调用方法之前发生事情,比如启动新事务,并在方法完成之后,如提交或者回滚交易。当你描述你希望e1和e2回滚时,那么e3应该被提交,这将需要在方法的中间执行事务代码,因此使用建议将不起作用。

对于您想要的交易控制级别,您将不得不诉诸Spring's programmatic transaction API

编辑:看看你的评论我可能误解了你想要的东西。如果你可以识别一组你想要一起进行的事情,无论是全部还是全部,你可以用标记事务的方法将它们组合在一起,并且有一个非事务性的方法在循环中调用方法并进行异常处理围绕每次调用事务方法。

答案 1 :(得分:0)

您需要向注释添加RollbackFor属性。像这样的东西:  @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Throwable.class)

答案 2 :(得分:0)

默认情况下,仅回滚未经检查的异常(即java.lang.RuntimeException的子类)。

您需要将 rollbackFor 添加到@Transactional注释。

您也没有异常处理,因此e3不会被执行。

答案 3 :(得分:0)

可能您已经提交了上一个事务,因此Java部分无法再将其回滚。

我猜:

  • 您的数据库提交每次插入/更新
  • 你的DAO做到了