This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
I have a query related to the usage of entity manager's merge() operation.
I have come across lots of code where entities are being fetched using find and inside transactions. All the code which modifies these fetched entities as well is being executed inside the scope of transactions. And the entities are being updated with calls to em.merge().
Isn't this an avoidable call? Since the entity find() is happening inside a transaction, it will be in the scope of persistence context and any modifications to the entity should be visible to the persistence context. And the persistence provider (I am using hibernate) should commit these changes to the database irrespective of whether merge() is invoked or not? Is my understanding correct?
The spec says "If X is a managed entity, it is ignored by the merge operation, however, the merge operation is
cascaded to entities referenced by relationships from X if these relationships have been annotated
with the cascade element value cascade=MERGE or cascade=ALL annotation.".
So, I hope I can safely remove all the merge() calls being made.
Also wondering, If the merge() calls are left as such, would they have any impact on performance?
Another question on the statement from the spec is - If X is a managed entity, the entities reference by X should also have been managed.
So, merge operation cascaded from X should also be ignored on the referenced entities. Is that correct?
You are correct - if the entities are retrieved within a valid transaction then any changes to those objects will be persisted when the transactions ends.
You should safely be able to remove those calls, but make sure you test all the functionality once removed as transaction configuration can often be done incorrectly, and if explicit merge calls were being used you may never have known.
You should remove them as this isn't really what the merge() functionality was designed for - its purpose was to handle merging of detached entities. Care should be taken when using merge - and if you wish to continue using the entity after merging you should make sure you reset it:
x = em.merge(x);
if you don't then x will often be unusable after merge has occured and you will likely see strange results.