2011-11-09 137 views
7

我有一个@Service类,它有一个@Transactional方法,在同一个类上调用另一个@Transactional方法。我正在测试回滚行为,我发现它不能正常工作。该代码看起来是这样的:Spring嵌套的@Transactional方法和回滚

@Service 
public class DefaulService implements ervice 
{ 
    @Transactional 
    public void methodOne() 
    { 
     methodTwo(); 

      //question edited 
      //this seems to be the problem 
      this.serviceDAO.executeUpdateOperation(); 

     //test rollback 
     throw new RuntimeException(); 
    } 

    @Transactional 
    public void methodTwo() 
    { 
     //DAO stuff 
    } 
} 

运行methodOne我检查数据库和变化是有后,即使日志显示“JDBCTransaction - 回滚”。

如果我单独调用methodTwo并在其末尾添加异常,则更改会正确回滚。

有没有办法让方法正确回滚嵌套的@Transactional调用期间发生的更改?我的印象是REQUIRED的默认传播会实现这一点,但似乎并没有奏效。由于

UPDATE

好吧,我只注意到别的东西。在抛出异常之前,我正在调用服务的dao并通过“executeUpdate”执行手动更新。如果我评论这一行,则嵌套回滚将起作用。所以看来问题实际上是调用DAO并运行executeUpdate查询。但是,这不应该在当前交易中运行吗?

+0

您是否知道从'methodOne()''@ Transactional'注释中调用'methodTwo()'时忽略了?有关更多详细信息,请参阅我的[文章](http://nurkiewicz.blogspot.com/2011/10/spring-pitfalls-proxying.html)。但是这不会导致你的问题,但值得去了解。 –

+0

是的,但由于MethodTwo可以独立调用,因此它需要自己的注释。现在我难以理解为什么executeUpdate会导致事务被提交,尽管也许这是默认行为。 – JayPea

+1

serviceDao的事务传播是什么?是否有任何机会REQUIRES_NEW? – Hendrik

回答

1

当你调用方法时,你肯定会从bean工厂获得“服务”的实例,对吗? bean工厂需要建立一个代理来实现每个方法调用的事务逻辑。我只是觉得这只有当“外人”通过代理调用方法时才起作用,并且在一个方法调用另一个方法时不一定有效,因为该方法是实现对象内部的直接调用,并且不通过AOP代理。

+0

这取决于您正在使用哪种AOP方法。检查Tomasz Nurkiewicz的[link](http://nurkiewicz.blogspot.com/2011/10/spring-pitfalls-proxying.html)。这也无法解释JayPea描述的行为。 –