A detached entity is an instance that retains its database identity and loaded state but is no longer managed by a persistence context. For example, an EntityManager can find an entity during a unit of work; after the context closes, the application still holds the instance, but its data may become stale. Changes to it are not automatically written to the database. section 10.1.1 section 10.3.3
Detachment changes what the application can rely on:
- Closing the persistence context detaches its entities. EntityManager.detach(entity) detaches one instance earlier; EntityManager.contains(entity) then returns false. section 10.1.1 section 10.3.3
- Loaded values can be read after closure, but an uninitialized proxy cannot load more data on demand. Initialize needed data before closing the context. section 10.2.4 section 10.2.3
- Within one persistence context, repeated lookups of an identifier return the same Java instance. Across contexts, instances with the same database identity need not be the same Java object. section 10.3.1
To save detached changes in a new unit of work, call EntityManager.merge(detachedEntity). Merge copies state onto a managed instance with the same identifier, loading one if necessary, and returns that managed instance. Continue working with the returned reference, not the old detached reference. Hibernate synchronizes the managed changes when the context flushes. section 10.3.4
Detach, then merge
After loading a User, call em.detach(user) and check that em.contains(user) is false. Change its username while detached. In a new persistence context and transaction, assign User managed = em.merge(user); make any further changes to managed before committing. section 10.3.3 section 10.3.4
Do not equate database identity with Java equality. With default Object.equals(), two instances loaded in different contexts can compare unequal despite having the same identifier; a HashSet can retain both. Where equality must work across contexts, implement equals() and hashCode() using a suitable business key, accounting for Hibernate proxies. section 10.3.1 section 10.3.2
Path: managing-data/src/test/java/com/manning/javapersistence/ch10 /SimpleTransitionsTest.java – mergeDetached() detachedUser.setUsername("johndoe"); em = emf.createEntityManager(); em.getTransaction().begin(); User mergedUser = em.merge(detachedUser); mergedUser.setUsername("doejohn"); em.getTransaction().commit(); em.close();
Follow the two references in the merge example: the detached User supplies changes, while the returned User is the managed instance used for subsequent edits. section 10.3.4
