This week's book giveaway is in the OCPJP forum. We're giving away four copies of OCA/OCP Java SE 7 Programmer I & II Study Guide and have Kathy Sierra & Bert Bates on-line! See this thread for details.
I have a doubt regarding merging new entity bean instances.
Section 3.2 of the JPA spec. defines both new and managed instance's states:
A new entity instance has no persistent identity, and is not yet associated with a persistence context. A managed entity instance is an instance with a persistent identity that is currently associated with a persistence context.
Further, under section 188.8.131.52 (Merging Detached Entity State) it explains what happens when you call EntityManager.merge() on a new instance:
The semantics of the merge operation applied to an entity X are as follows: [...] If X is a new entity instance, a new managed entity instance X' is created and the state of X is copied into the new managed entity instance X'.
Finally, in section 3.2.3 (Synchronization to the Database) the spec. states:
The semantics of the flush operation, applied to an entity X are as follows: If X is a managed entity, it is synchronized to the database.
At this point, I began to wonder what would happen with both instances when transaction commits. My reasoning went like this:
1) When we create a new entity bean instance, that instance state is new instance. 2) We call its setter method(s) to initialize the new instance's state. 3) After calling merge on that instance, another instance is created and that newer instance is managed. The newer (and managed) instance's state is a copy of the first instance we created. 4) At a given time, when transaction commits, what happens with the managed instance? Does it get synchronized to the database?
So, I decided to test it under Glassfish and the result was a new row inserted in the database. It was as if I called EntityManager.persist().
The only difference I see between calling persist() and merge() on a new instance is that in the first case the instance itself becomes managed, and with merge() only the newer copy of the instance gets managed, not the original one.
Is this reasoning right?
And to make things a little more confusing, I stumbled under the following while reading thru section 3.3.2 (Transaction Rollback) of the JPA spec.:
Transaction rollback typically causes the persistence context to be in an inconsistent state at the point of rollback. In particular, the state of version attributes and generated state (e.g., generated primary keys) may be inconsistent. Instances that were formerly managed by the persistence context (including new instances that were made persistent in that transaction) may therefore not be reusable in the same manner as other detached objects�for example, they may fail when passed to the merge operation.
And there's a footpage note that reads:
It is unspecified as to whether instances that were not persistent in the database behave as new instances or detached instances after rollback. This may be implementation-dependent.
Under which circumstances will the merge operation fail in that case? Does it mean it may fail if the instance that we tried to make persistent in that rolled back transaction behaves as a new instance after the rollback? If that's the case, this situation contradicts the results I have seen in my little experiment and what the spec. was saying before.