I'm reading "EJB3 In Action" and am on page 304.
In the book, the authors are writing an ItemManagerBean to show how JPA operations work.
One of their methods is for refreshing the Entity back to the way it is in the DB - "allow the user to start over with modifying a listing (think of an HTTP form's "reset" button)".
My question is why the merge operation was necessary? As I understand it, refresh() will bring an Entity into the Persistence Context, and their diagram on page 298 would back this up. So as I see it, the merge is unnecessary. The errata doesn't list this as a mistake, so am I misunderstanding something here?
As far as I remember, merge() is used to put a detached or new entity in the persistence context. refresh() needs needs a managed entity, so if the entity is detached or new, it will fail. To prevent this, merge() is being used before calling refresh().
To clarify Cristophe's response, here's my take on the workflow:
1. merge(item) will take the detached 'item' and make it managed by retrieving the corresponding Item values from the database (assuming, of course, that it exists in the database); however, merge() takes any changed values from 'item' and overwrites the values retrieved from the database
2. to fix this, refresh() is called which reverts the changed values to their original database values
Result: the changes to 'item' have been undone
Joined: Nov 11, 2006
Hi Christophe and Peter,
Thank you both for your responses - much appreciated. I've not been ignoring this thread, just leaving it to gather responses whilst I study other areas.
I've just been re-covering this section (and writing a test/learning app) and now see why the merge is necessary (it turns the Entity into a managed one). It's like the opposite of detach. It's a shame that the changes you don't want have to be written to the persistence context (by the merge) and then have to be written back over (by the refresh), but I understand why it's happening.
I've come to the conclusion (difficult if you can't see the book, but useful if authors are reading) that the diagram on p298 is confusing. It shows an entity going from a detached to a managed state and is listed with the operations "merge()/refresh()". This implies that refresh results in a managed Entity, which we know not to be true. The slash also doesn't mean that these operations must be sequential as other parts of the diagram use the slash as the normal 'either/or' operator.
Persist - makes an Entity managed. To invoke this, my Entity must not be managed, or I risk getting a EntityExistsException.
Merge - returns a managed Entity. It doesn't say that it'll throw an exception if the Entity is already managed, although the call wouldn't make much sense.
Refresh - (topic of this thread). Throws an IllegalArgumentException if "the entity is not managed". So, we'd need to make it managed somehow and so merge could be used.
Remove - Throws an IllegalArgumentException if the Entity "is a detached entity". Same as merge.
Joined: Sep 16, 2009
Your assessment is correct. You may want to reference the EJB JPA Spec; it's a bit of a read, but has real good info in it.
From the spec:
The state of a managed entity instance is refreshed from the database by invoking the refresh method
on it or by cascading the refresh operation.
This is quite useful when using long transactions, handling changes to cascaded children and in locking scenarios.
Example (not verified for correctness, only here to show a generalized example -- there are many (better) ways to do locking):