Grails事务性服务在事务性控制器操作内部调用



这两个控制器动作有什么区别:

  @Transactional
    def save(SomeDomain someDomain) {
        someDomain.someProperty = firstService.createAndSaveSomething(params)    //transactional
        someDomain.anotherProperty = secondService.createAndSaveSomething(params) //transactional
        someDomain.save(flush: true)
    }

    def save(SomeDomain someDomain) {
        combinedService.createAndSave(someDomain, params) //transactional, encapsulating first and second service calls
    }

我的目的是在事务失败时回滚整个save()操作。但不知道该用哪个

您可以使用这两种方法。

清单1将在firstServicesecondService抛出异常时回滚控制器事务。

清单2中的

(我希望combinedServicecreateAndSave方法用@Transactional注释)将在createAndSave抛出异常时回滚事务。使用这种方法的一大好处是,理论上该服务方法可以在其他控制器中重用。

关于@Transactional的一个关键点是需要考虑两个独立的概念,每个概念都有自己的范围和生命周期:

  1. 持久性上下文
  2. 数据库事务

事务注释本身定义了单个数据库事务的范围。数据库事务发生在持久性上下文的范围内。代码:

@Transactional
    def save(SomeDomain someDomain) {
        someDomain.someProperty = firstService.createAndSaveSomething(params)    //transactional
        someDomain.anotherProperty = secondService.createAndSaveSomething(params) //transactional
        someDomain.save(flush: true)
    }

持久性上下文在JPA的EntityManager中,使用Hibernate会话在内部实现(当使用Hibernate作为持久性提供者时)。代码:

def save(SomeDomain someDomain) {
        combinedService.createAndSave(someDomain, params) //transactional, encapsulating first and second service calls
    }

注意:持久化上下文只是一个同步器对象,它跟踪一组有限的Java对象的状态,并确保对这些对象的更改最终持久化回数据库。

结论:声明性事务管理机制(@Transactional)非常强大,但它很容易被滥用或错误配置。

了解它的内部工作原理有助于在机制完全不工作或以意想不到的方式工作时进行故障排除。

最新更新