Skip to main content

DAO insertOrUpdate() method: how to implement using JPA?

1 reply [Last post]
ljnelson
Offline
Joined: 2003-08-04

I have a SLSB that explicitly saves a data transfer object to disk, if it already exists, or creates a new one on disk if it doesn't.

The DTO is now an @Entity, and I'd like to implement this DAO to use the JPA.

I am getting quite confused with how to do this. Simply calling:

entityManager.merge(dto);

...seems to do the right thing in all cases. Could this really be this simple? When, if ever, would I be required to invoke the persist() method? I'm feeling queasy that I never invoke this in the code anywhere.

I should mention that the object being inserted/updated is always coming from a fat client, and is hence pretty much guaranteed to be detached. What puzzles me is the behavior of the merge() method in the case of this-is-a-brand-new-never-persisted-before DTO. I am surprised that this works. Should it? Is it guaranteed to? Is this Glassfish-specific behavior?

Tentatively,
Laird

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
stvconsultants
Offline
Joined: 2006-03-06

A question that has come up in another forum is what happens when you call em.merge on an instance where the entity to which the instance refers to has been removed.

i.e.

Thread 1
[code]
AnEntity X = em.find(AnEntity.class, "key1");
em.detach(X);
doLongRunningTask();
X = em.merge(X);
// what has happened in this call to em.merge
[/code]
Thread 2 (possibly in a different VM)
[code]
AnEntity Y = em.find(AnEntity.class, "key1");
em.remove(Y);
[/code]

Now seemingly the people over at hibernate state that the call to em.merge will add the detached instance back into the database (as it is now does not correspond to a persisted entity and is therefore a new entity that should be persisted)

A different reading of the spec might lead one to suspect that an OptimisticLockException should be thrown... although I am unsure as to whether this is a good thing either.

Some clarification would be good too, as otherwise we'll all be going:

[code]
if (em.getReference(AnEntity.class, X.getId()) != null) {
X = em.merge(X);
} else {
throw new OptimisticLockException();
}
[/code]

everywhere we have a em.merge ;-)