Card 04/ 07
Detached Entities: Changes That Never Reach the Database
Change a field after detach and flush, and nothing is written, with no error either.
A detached entity is one the persistence context (JPA's record of the entities it is tracking in the current transaction) has stopped watching, and changes to it are not written anywhere. JPA's automatic saving of changed entities, dirty checking, only covers managed entities, the ones JPA is currently tracking, so a field changed after detach() stays changed in memory and never reaches the database.
emp is loaded, detached, and has its name changed directly, and then the persistence context is flushed. Nothing happens: no error and no write.
Employee emp = em.find(Employee.class, id);
em.detach(emp);
emp.name = "changed-after-detach";
em.flush();flushed after modifying detached entity (should NOT throw, and should NOT persist the change)
re-read from a fresh call, name = Alex (should still be Alex, not changed-after-detach)The field really did change, in memory, on that one reference. But detach() turned off the watching for that object, so the flush had nothing to write, and a fresh read still finds Alex.
It is costly because it looks exactly like code that works. The same three lines without the detach() would save the change, and in real applications the detaching usually happens out of sight, when a transaction ends before the change is made.
merge() is the way back. It does not turn tracking on for the same object: it copies that object's state onto a managed instance and returns it. The original reference stays detached, so keep working with the object merge() returns.
← → move through sections and cards