这两个控制器操作之间的区别是什么:
@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()动作。但不确定我使用哪一个。
答案 0 :(得分:3)
您可以使用这两种方法。
当firstService
或secondService
抛出异常时,您的商家信息#1将回滚控制器交易。
在列表#2中(我期望createAndSave
的{{1}}方法用combinedService
注释)如果@Transactional
抛出异常,将回滚事务。使用这种方法的一大优点是,这种服务方法在理论上可以在其他控制器中重复使用。
答案 1 :(得分:0)
关于@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
}
持久化上下文在JPA中是EntityManager,使用Hibernate Session在内部实现(当使用Hibernate作为持久性提供程序时)。你的代码:
@Transactional
注意:持久化上下文只是一个同步器对象,它跟踪一组有限的Java对象的状态,并确保对这些对象的更改最终保留在数据库中。
结论:声明式事务管理机制(<core-label>
)功能非常强大,但可能会被滥用或错误配置。
在机制完全无法正常工作或以意想不到的方式工作时,了解内部工作原理非常有用。