问题
Given:
- controller
PersonController
with a@Transactional
actionsave
- service
PersonService
with a methodpopulateProperties(PersonInstance)
being called from the controller action
I'd like to populate personInstance
properties based on some data already persisted in the database, like this:
def personLookupData = PersonLookupData.findByUsername(personInstance.username)
personInstance.firstName = personLookupData.firstName
The findByUsername
method flushes the hibernate session and in order to avoid it (because it has been giving me problems described here), I do this:
def personLookupData = PersonLookupData.withNewSession { PersonLookupData.findByUsername(personInstance.username) }
personInstance.firstName = personLookupData.firstName
This does what I want (lets me use findBy
without flushing the session), and this is fine when there is only a couple of findBy
s to use, but given a deeper call stack (in terms of services) and more database lookups in different places, using withNewSession
everywhere becomes a bit ugly.
Apart from making a PersonLookupService
which will collect all the required data in one withNewTransaction
block and return it, is there any other nice (groovy) way of doing this?
回答1:
I think you should move @Transactional from PersonControlller to PersonService.
If you have more service calls to include in the same transaction, you need to use a Transaction boundary gateway, that's marked as @Transactional and calls all services you need for the current business case.
It's not the responsibility of the MVC components to control transactions. The transactions boundary are handled by the service layer.
来源:https://stackoverflow.com/questions/27502758/using-findby-in-transactional-context