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