Grails,服务交易无法正常工作

时间:2015-04-24 15:27:22

标签: grails transactions

Grails版本2.4.3

我的代码如下,当我在正在处理的方法中抛出运行时异常时,我可以继续并保存。但是,如果我在SecondLevelService中抛出运行时异常,则会出现错误 secondLevelService.TestA()它所做的一切 throw new RuntimeException('This is a Run time exception Second Level')

  

事务已回滚,因为它已被标记为仅回滚

因为错误表示它已回滚并且没有保存任何内容。

任何人都可以帮助我理解为什么差异,我希望它更接近方法中抛出的异常。通过关闭二级服务中的事务来处理错误,但这不符合我的要求。

class FirstLevelService {
    SecondLevelService secondLevelService
    def TestA() {
        com.Author author = null
        com.Book book =  null


        try {


            //Create a database record
            author = new com.Author(firstName:'TestXXX', lastName: 'User XXX' )
            book = new com.Book(title: 'Test Book XXX', pageCount: 1 )

            author.addToBooks(book)

            println 'Book Save'
            author.save(failOnError:true)
            println 'Is Dirty 1st Save:' + author.isDirty()
            println author.books?.size()

            //Fail with Runtime exception this is do other things to the book and author
            throw new RuntimeException('This is a Run time exception')
            //secondLevelService.TestA()
        }
        catch (RuntimeException re) { //Cause I am catching any saving should be okay
            println 'Exception caught'
            println re.message
        } finally {

            //But make the change to author anyway
            println 'Change the first Name'
            author.firstName = 'TestYYY ' + new Date().toString()
            println 'Is Dirty before Save:' + author.isDirty()


            println 'Save Change the first Name: ' + author.firstName

            if (!author.validate()) {
                author.errors.each {
                    println it
                }
            }

            println 'Is Dirty before 2nd Save:' + author.isDirty()
            author.save(failOnError:true)
            println 'Is Dirty:' + author.isDirty()
        }
    }
}

1 个答案:

答案 0 :(得分:1)

基本上这正是预期的行为。在服务中引发并且未在同一服务中捕获的RuntimeException导致事务的回滚(请参阅grails service docs:12.1声明性事务)。

如果你想绕过它,你有不同的可能性。第一个是,此回滚行为仅适用于RuntimeExceptions或错误 - 不适用于已检查的异常。这是事实,尽管groovy对已检查的异常与未经检查的异常有一点不同的理解。文档在这里提出的观点是,Spring意识到了这一点,这就是原因。

我能想到的另一个可能的解决方案不是在两个服务中共享交易。这应该有效,因为默认的事务传播行为是PROPAGATION_REQUIRED。这意味着,如果第二个服务创建了运行时异常,则会在整个事务中调用transaction.setRollbackOnly()。因此,您可以在第二个服务中要求新的交易,也可以根本不使用交易。