Grails 或 Spring 方法级事务

Grails or Spring Method Level Transaction

我是spring/grails交易的新手,看完后还是不太清楚,所以我把它发在这里,

我有一个服务 class 被注释为 @Transactional 我有一些方法,其中一些被注释为

@Transactional(propagation = Propagation.REQUIRES_NEW)

其中一些不是。

@Transactional
class SomeService {

    def findJob() {
        MyInstance myInstance = getMeAJob();
        if (myInstance) {
            doSomeThing(myInstance)
            doTask()
        }
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception)
    private doSomeThing(MyInstance myInst) {
        myObj = MyInstance.lock(myInst.id)
        try {
            differentObj = doTask(myObj)
            myObj.save()
            doAnotherThing()
            }
        } catch (Exception e) {

            log("Error in doAnotherTask")
        }
    }


    private doAnotherThing(MyInstace myInst) {
        perform some update on myInst
        myInstant.save(flush: true)
    }
    private doTask() {    
    }

当您有 class 范围注解时,任何未注解的方法都会使用这些设置,而注解方法会使用该注解中的设置覆盖 class 级别的设置。

但是请注意,当使用 Spring 的注释支持(使用 @org.springframework.transaction.annotation.Transactional)注释时,仅支持 public 方法。不会有错误,但注释会被静默忽略。

但是即使你做了 doSomeThing public(通过删除 private 关键字隐式地或通过将它显式地更改为 public)它也不会做你期望的事情,当你从 findJob 呼叫 doSomeThing。这是因为 Spring 的注解会在 运行 时触发创建您的 class 的代理。在这种情况下为您的服务注册的 Spring bean 是一个代理实例,它有一个 class 的 "real" 实例作为其委托。所有事务性 public 方法都被代理拦截,starts/joins/etc。事务,然后调用您的服务方法。一旦您成为 "underneath" 服务实例中的代理,所有方法调用都是直接的,任何注释设置都无效。要使其正常工作,您需要调用 Spring bean 上的方法并通过代理启动新事务。

要避免此代理问题,请改用 Grails @grails.transaction.Transactional 注释。它支持与 Spring 注释相同的事务功能,但不是创建代理,而是 AST 转换重写您的方法以将它们包装在事务中。这使得可以像您正在做的那样进行直接方法调用,并在注释属性定义的其他事务语义下创建新事务或运行。

a talk 前一阵子在 Grails 中使用事务可能会有所启发。