【问题标题】:Grails or Spring Method Level TransactionGrails 或 Spring 方法级事务
【发布时间】:2015-11-18 12:36:27
【问题描述】:

我是 spring/grails 交易的新手,阅读后我仍然不清楚,所以我在这里发布它,

我有一个注释为@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() {    
    }
  • 假设,我有来自班级级别的事务 t1 和 t2 来自 doSomething() 的事务 - REQUIRES_NEW。
  • 将在 t1 中执行的方法 - findJob() 和 doTask()
  • 将在 t2 中执行的方法 - doSomeThing() - 不会影响 异常情况下的“t1”(回滚)

    哪一个用于 doAnotherThing() 方法?既然我是从 doSomething() 调用它?

【问题讨论】:

    标签: spring grails transactions spring-transactions


    【解决方案1】:

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

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

    但是,即使您公开 doSomeThing(通过删除 private 关键字隐式或通过将其显式更改为 public),当您从 findJob 调用 doSomeThing 时,它也不会像您期望的那样。这是因为 Spring 的注解会在运行时触发创建类的代理。在这种情况下,为您的服务注册的 Spring bean 是一个代理实例,它具有您的类的“真实”实例作为其委托。所有事务性公共方法都被代理拦截,该代理启动/加入/等。一个事务,然后调用你的服务方法。一旦您在服务实例中的代理“下方”,所有方法调用都是直接的,并且任何注释设置都无效。要让它工作,您需要调用 Spring bean 上的方法并通过代理启动新事务。

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

    我之前在使用 Grails 中的事务时使用了 a talk,这可能会有所启发。

    【讨论】:

    • 谢谢@Burt,我发现谈话和你的回答很有帮助。我正在使用@grails.transaction.Transactional,并将我的方法更改为公开。所以现在我假设doAnotherThing() 将在事务 t2 中执行?
    • 是的,它应该创建第二个事务。
    猜你喜欢
    • 1970-01-01
    • 2015-03-26
    • 2018-03-09
    • 2013-03-08
    • 2017-11-21
    • 1970-01-01
    • 2011-02-21
    • 2018-06-01
    • 1970-01-01
    相关资源
    最近更新 更多