tags:

views:

51

answers:

2

Using JPA which method should I follow while updating?

approach 1

obj o = new obj()
o.setName('val')
set other values
entitymanger.merge(ibj)

approach 2

obj o = getObjFromDb(obj)
obj.setval(name)
//not am not updating other attributes

entitymanage.merge(obj)
+2  A: 

You first approach creates new object, so merge wouldn't update object, but place new one into DB. So approach 2 is look better. But looking at you comment about getObjFromDb about transaction, I have to note that methods: merge, persist, remove should be done inside transaction scope.

So better solution pseudo-code is:

boolean transactionClosed = false;
entitymanage.getTransaction().begin();
try{
   obj o = entitymanage.find( someKey );
   o.setval(name);
   entitymanage.getTransaction().commit();
   transactionClosed = true;
}
finally{
   if( !transactionClosed )
       entitymanage.getTransaction().rollback();
}
Dewfy
...or better say approach 2 looks the only approach. +1
Adeel Ansari
first appraches also updates a existing record
akp
@akp - I made accent that **merge** - must be used for update only, but not for creation new object in database.
Dewfy
This is incorrect, merging a NEW entity doesn't throw an exception (and anyway, I'm assuming the OP is setting the database identifier so it's actually a detached entity).
Pascal Thivent
@Dewfy Sorry but merge can create a new entity: JPA is clear: 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.
Arthur Ronald F D Garcia
@Arthur Ronald F D Garcia: thanks, that you point me on it
Dewfy
@Pascal Thivent: thanks that you point me on it
Dewfy
You're welcome. But you should fix your answer :)
Pascal Thivent
@Pascal Thivent - fixed
Dewfy
+1  A: 

You really need to understand the semantics of the merge operation so I'll repeat what the JPA spec is saying:

3.2.4.1 Merging Detached Entity State

The merge operation allows for the propagation of state from detached entities onto persistent entities managed by the EntityManager.

The semantics of the merge operation applied to an entity X are as follows:

  • If X is a detached entity, the state of X is copied onto a pre-existing managed entity instance X' of the same identity or a new managed copy X' of X is created.
  • 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'.
  • If X is a removed entity instance, an IllegalArgumentException will be thrown by the merge operation (or the transaction commit will fail).
  • 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.
  • For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL, Y is merged recursively as Y'. For all such Y referenced by X, X' is set to reference Y'. (Note that if X is managed then X is the same object as X'.)
  • If X is an entity merged to X', with a reference to another entity Y, where cascade=MERGE or cascade=ALL is not specified, then navigation of the same association from X' yields a reference to a managed object Y' with the same persistent identity as Y.

The persistence provider must not merge fields marked LAZY that have not been fetched: it must ignore such fields when merging.

Any Version columns used by the entity must be checked by the persistence runtime implementation during the merge operation and/or at flush or commit time. In the absence of Version columns there is no additional version checking done by the persistence provider runtime during the merge operation.

In other words, the merge operation copies the state of the passed entity to a managed entity with the same database identity (that will be loaded in the persistence context if necessary) and then returns a reference to that managed entity (and the object passed is not attached to the persistence context).

Back to the initial question now. In both case, the database values will be overridden with the full state of the passed entity, including non null (and null) values. In practice:

  • approach 2 i.e. working directly on detached entities is easier
  • approach 1 sounds like the DTO anti pattern and means more pain

Prefer approach 2 if you can.

Related question

Pascal Thivent