问题
A Grails 2.3.4
application is connecting to an Oracle database using the following domain class:
class Person {
String name
static mapping = {
id column: "PERSON_ID", generator: "sequence", params: [sequence: 'person_seq']
}
}
The PersonController
makes a call to a method in PersonService
and it makes a call to UtilService
. The method in UtilService
being called has some logic based on wether this Person
object is new:
if (personInstance.id == null) { ... }
What I have found is that the id
property of personInstance
(which is passed through the method calls described above) is assigned when the UtilService
is called.
The controller action calling PersonService
is @Transactional
, and the services do not have any transaction configuration.
So, a couple of questions:
- When is
id
value assigned by GORM (I assumed at insert but that seems wrong)? - Is there a better way of checking if the object is new (
isAttached()
returnstrue
so that's not good for me)?
EDIT: save()
has not been called on the personInstance
when UtilService
does the id
check.
回答1:
The id is assigned when you call save()
. For most persistence calls, Hibernate delays flushing the change until it feels it has to flush) to ensure correctness. But save()
calls are treated differently. I believe the motivation is that even if we know that flush() will eventually be called, even if it's at the very end of the request, we want to retrieve the id early so it doesn't suddenly change.
Note that a service that does "not have any transaction configuration" is transactional - the only way to get a non-transactional service is to remove all @Transactional
annotations (the newer Grails annotation and the older Spring annotation) and add
static transactional = false
All other services are transactional, although you can configure individual methods to be ignored ## Headin.
回答2:
Turns out, I had a findBy
which was flushing the session:
utilService.someMethod(Person.findByUsername(username))
It was at this point that the id
was populated.
Got around it by using withNewTransaction
:
def personInstance = Person.withNewSession { Person.findByUsername(username) }
utilService.someMethod(personInstance)
Which now leads me onto the next question...
来源:https://stackoverflow.com/questions/27309229/when-does-grails-assign-an-id-to-an-object