Hibernate 捕获grails事务上的运行时异常

Hibernate 捕获grails事务上的运行时异常,hibernate,grails,gorm,quartz-scheduler,Hibernate,Grails,Gorm,Quartz Scheduler,目前,我们有一个调用事务服务的grails作业。当从服务中抛出异常时,hibernate的行为变得异常。我们正在使用Grails2.4.4和hibernate:3.6.10.18 因此,在我的作业中,我在execute方法上有以下内容: Model.withTransaction { -> try { service.updateDatabase() service.method()//throws runtime exception

目前,我们有一个调用事务服务的grails作业。当从服务中抛出异常时,hibernate的行为变得异常。我们正在使用Grails2.4.4和hibernate:3.6.10.18

因此,在我的作业中,我在execute方法上有以下内容:

Model.withTransaction { ->
    try {
        service.updateDatabase()
        service.method()//throws runtime exception
        } catch(RuntimeException e) {
            //do something
    }
}
奇怪的是,
updateDatabase
操作确实会回滚。查看日志,我可以验证它是否在catch块中通过,但仍然有日志表明仍然抛出异常。我想这就是为什么交易会倒退

但是如果我直接在作业上抛出
RuntimeException
,它不会回滚数据库事务,异常会被干净地捕获。在我的印象中,这应该是正确的行为,并且应该与从服务内部抛出异常相同

Model.withTransaction { ->
    try {
        service.updateDatabase()
        throw new RuntimeException()
        } catch(RuntimeException e) {
            //do something
    }
}
这正常吗?
这是虫子吗

预期的行为是:

Model.withTransaction { -> // Creates new Transaction
    try {
        service.updateDatabase() // uses the same Transaction that was created before
        service.method() // uses the same Transaction that was created before
                         // throws runtime exception
                         // sets Transaction as rollbackOnly
        } catch(RuntimeException e) {
            //do something
    }
} // as the Transaction was set as rollbackOnly it rollbacks everything that was done before
基本上,这是预期的行为,现在是解释

您的所有服务方法都是事务性的,因为您的服务在其名称上方有一个@Transactional

@Transactional
class MyTransactionalService {
...
}
默认情况下,每个事务方法都有PROPAGATION.REQUIRED属性集

/**
* Support a current transaction, create a new one if none exists.
* Analogous to EJB transaction attribute of the same name.
* <p>This is the default setting of a transaction annotation.
*/
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED)
只将一个方法设置为@Transactional,则只将该方法设置为事务性方法,而不是将所有方法都设置为事务性方法

我制作了一个项目作为示例,这样您就可以运行测试并自己检查它,我还设置了log4j来显示事务的生命周期,这样您就可以更好地理解它,您只需要运行MyProcessorIntegrationSpec.groovy


希望有帮助

我不明白你的问题,如果你帮我解决,我就能帮你。首先你说“奇怪的是,updateDatabase操作没有回滚”,然后说“我想这就是为什么Transaction正在回滚。”。请帮助我了解updateDatabase ir是否正在回滚。@juandiegoh很抱歉,我更新了问题。我回答了我认为是你的问题,但我仍然不明白。你的案子不会倒退,你认为“正确的行为”也不会倒退。@juandiegoh再次道歉,对我的问题的更正已被应用。在两个服务调用上包装事务意味着service.updateDatabase和service.method将位于同一事务中,无论我是否删除服务方法上的注释,对吗?因此,如果我将method()设置为非事务性的,那么它仍然是事务性的。正如您所说,使用作业的事务。我是否正确地假设捕获运行时异常意味着不再将其设置为仅回滚?这就是为什么第二个场景不会在每次事务方法以RuntimeException结束时回滚,它会将事务设置为rollbackOnly。如果您按照我在回答中告诉您的那样设置服务,则意味着updateDatabase()是事务性的,而method()不是事务性的,因此,如果method以RuntimeException结束,它将不会将事务设置为rollbackOnly。第二种场景没有回滚的原因是,没有事务性方法结束时抛出异常。updateDatabase()未以异常结束,Model.withTransaction{….}也未以异常结束。
class YourService {

    @Transactional
    def updateDatabase() {
        //...
    }

    def method() {
        //...
    }
}