Grails或Spring方法级别事务

pkr*_*ety 0 grails spring transactions spring-transactions

我是春季/学生交易的新手,阅读后我仍然不清楚,所以我在这里发帖,

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

@Transactional(propagation = Propagation.REQUIRES_NEW)
Run Code Online (Sandbox Code Playgroud)

其中一些不是.

@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() {    
    }
Run Code Online (Sandbox Code Playgroud)
  • 假设我有来自类级别的事务t1和来自doSomething()的t2事务 - REQUIRES_NEW.
  • 将在t1中执行的方法 - findJob()和doTask()
  • 将在t2中执行的方法 - doSomeThing() - 在异常情况下不会影响"t1"(回滚)

    doAnotherThing()方法将使用哪一个?因为我是从doSomething()调用它的?

Bur*_*ith 5

如果您有类范围注释,则任何未注释的方法都会使用这些设置,注释方法会使用该注释中的设置覆盖类级别设置.

但请注意,当使用Spring的注释支持(带有@org.springframework.transaction.annotation.Transactional)注释时,仅支持公共方法.不会出现错误,但会自动忽略注释.

但即使你公开doSomeThing(通过删除private关键字隐式地或通过将其更改为显式public),它将无法按照您的预期doSomeThing进行操作findJob.这是因为Spring的注释会在运行时触发创建类的代理.在这种情况下为您的服务注册的Spring bean是一个代理实例,它具有您的类的"真实"实例作为其委托.所有事务公共方法都被代理拦截,它启动/加入/ etc.一个事务,然后调用您的服务方法.一旦你在服务实例中的"代理"下面,所有方法调用都是直接的,任何注释设置都没有效果.要使它工作,您需要在Spring bean上调用该方法并通过代理来启动新事务.

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

我做了一个谈话而回上可能会提供一些线索Grails的使用事务.