Hibernate / Spring - 在事务中回滚事务

时间:2015-12-14 13:41:27

标签: java spring hibernate transactional

给出这个示例代码:

public class MyServiceImpl implements MyService {
    @Transactional
    public void myTransactionalMethod() {
        List<Item> itemList = itemService.findItems();
        for (Item anItem : itemList) {
            try {
                processItem(anItem);
            catch (Exception e) {
                // dont rollback here 
                // rollback just one item
            }     
        }

    }

    @Transactional
    public void processItem(Item anItem) { 
        anItem.setSomething(new Something);
        anItem.applyBehaviour();
        itemService.save(anItem);
    }
}

这是我想要实现的目标:

  1. 如果发生异常,则只有processItem(anItem);才会回滚。
  2. 如果发生异常,myTransactionalMethod应该继续,这意味着for-each应该结束。
  3. 如果myTransactionalMethod内发生异常但processItem(anItem)不发生异常,则myTransactionalMethod应完全回滚。
  4. 是否有解决方案不涉及手动管理交易(没有注释)?

    编辑:我在考虑使用@Transactional(PROPAGATION=REQUIRES_NEW),但不知道它是否可以在同一个bean中运行。

2 个答案:

答案 0 :(得分:7)

这是一种常见的误解。 Spring事务通过代理实现。代理是你班级的包装。您正在访问同一课程中的processItem方法,即您没有通过代理,因此您无法获得任何交易。几年前I explained the mechanism in this answer

解决方案:如果您需要嵌套事务,则需要两个单独的Spring bean,它们都必须由@Transactional代理。

答案 1 :(得分:0)

看起来像NESTED交易的情况。 NESTED事务在具有保存点的外部事务中启动子事务,允许它回滚到该保存点。因为它是在外部转换结束时提交的嵌套事务。

    public class MyServiceImpl implements MyService {
    @Transactional
    public void myTransactionalMethod() {
        List<Item> itemList = itemService.findItems();
        for (Item anItem : itemList) {
            try {
               // If you want to call this method directly configure your transaction use to aspectJ for transaction handling or refactor the code. Refer - [http://stackoverflow.com/questions/3423972/spring-transaction-method-call-by-the-method-within-the-same-class-does-not-wo][1]
                processItem(anItem);
            catch (Exception e) {
                // dont rollback here 
                // rollback just one item
            }     
        }

    }

    @Transactional(PROPAGATION = PROPAGATION.NESTED)
    // Throw some runtime exception to rollback or some checkedException with rollbackFor attribute set in the above annotation
    public void processItem(Item anItem) { 
        anItem.setSomething(new Something);
        anItem.applyBehaviour();
        itemService.save(anItem);
    }
  }

请注意,我还没有尝试过以下代码,看看是否有帮助。如果需要,您可能需要调整它。事实上,我很乐意在不久的将来尝试使用这些代码。