这两个控制器动作有什么区别:
@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将在firstService
或secondService
抛出异常时回滚控制器事务。
(我希望combinedService
的createAndSave
方法用@Transactional
注释)将在createAndSave
抛出异常时回滚事务。使用这种方法的一大好处是,理论上该服务方法可以在其他控制器中重用。
关于@Transactional
的一个关键点是需要考虑两个独立的概念,每个概念都有自己的范围和生命周期:
- 持久性上下文
- 数据库事务
事务注释本身定义了单个数据库事务的范围。数据库事务发生在持久性上下文的范围内。代码:
@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
)非常强大,但它很容易被滥用或错误配置。
了解它的内部工作原理有助于在机制完全不工作或以意想不到的方式工作时进行故障排除。