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. 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.
In listing #2 (I expect the createAndSave
method of combinedService
to be annotated with @Transactional
) will rollback the transaction if createAndSave
throws an exception. 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:
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). 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.
Conclusion : The declarative transaction management mechanism ( @Transactional
) is very powerful, but it can be misused or wrongly configured easily.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.