问题
Given:
- controller
PersonControllerwith a@Transactionalactionsave - service
PersonServicewith 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 findBys 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