[英]grails transactional service calls inside transactional controller action
What's the difference between these two controller actions: 这两个控制器动作之间有什么区别:
@Transactional
def save(SomeDomain someDomain) {
someDomain.someProperty = firstService.createAndSaveSomething(params) //transactional
someDomain.anotherProperty = secondService.createAndSaveSomething(params) //transactional
someDomain.save(flush: true)
}
and 和
def save(SomeDomain someDomain) {
combinedService.createAndSave(someDomain, params) //transactional, encapsulating first and second service calls
}
My purpose is to rollback the whole save() action if a transaction fails. 我的目的是在事务失败时回退整个save()操作。 But not sure which one shoud I use.
但不确定我应该使用哪一个。
You can use both approaches. 您可以使用两种方法。
Your listing #1 will rollback the controller transaction when firstService
or secondService
is throwing an exception. 当
firstService
或secondService
引发异常时,清单1将回滚控制器事务。
In listing #2 (I expect the createAndSave
method of combinedService
to be annotated with @Transactional
) will rollback the transaction if createAndSave
throws an exception. 在上市#2(我希望
createAndSave
的方法combinedService
与被注解@Transactional
)如果将回滚事务createAndSave
抛出异常。 The big plus using this approach is that this service method is theoretically reusable in other controllers. 使用此方法的最大好处是,该服务方法在理论上可在其他控制器中重用。
One of the key points about @Transactional
is that there are two separate concepts to consider, each with it's own scope and life cycle: @Transactional
的关键点之一是要考虑两个单独的概念,每个概念都有自己的范围和生命周期:
The transactional annotation itself defines the scope of a single database transaction. 事务注释本身定义了单个数据库事务的范围。 The database transaction happens inside the scope of a persistence context.
数据库事务在持久性上下文的范围内发生。 Your code:
您的代码:
@Transactional
def save(SomeDomain someDomain) {
someDomain.someProperty = firstService.createAndSaveSomething(params) //transactional
someDomain.anotherProperty = secondService.createAndSaveSomething(params) //transactional
someDomain.save(flush: true)
}
The persistence context is in JPA the EntityManager, implemented internally using an Hibernate Session (when using Hibernate as the persistence provider). 持久性上下文在JPA中是EntityManager,使用Hibernate Session在内部实现(当使用Hibernate作为持久性提供程序时)。 Your code:
您的代码:
def save(SomeDomain someDomain) {
combinedService.createAndSave(someDomain, params) //transactional, encapsulating first and second service calls
}
Note : The persistence context is just a synchronizer object that tracks the state of a limited set of Java objects and makes sure that changes on those objects are eventually persisted back into the database. 注意:持久性上下文只是一个同步器对象,该对象跟踪一组有限的Java对象的状态,并确保最终将这些对象上的更改持久化回到数据库中。
Conclusion : The declarative transaction management mechanism ( @Transactional
) is very powerful, but it can be misused or wrongly configured easily. 结论:声明式事务管理机制(
@Transactional
)非常强大,但很容易被滥用或错误配置。
Understanding how it works internally is helpful when troubleshooting situations when the mechanism is not at all working or is working in an unexpected way. 在机制无法正常工作或无法正常工作的情况下进行故障排除时,了解其内部工作方式将很有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.