An entity becomes detached (unmanaged) on following actions:
- after transaction commit/rollback
- by calling
EntityManager.detach(entity)
- by clearing the persistence context with
EntityManager.clear()
- by closing an entity manager with
EntityManager.close()
- serializing or sending an entity remotely (pass by value).
Changes to a detached entity (changing fields, removing, refreshing etc) will not be synchronized to the database state.
A detached entity still has the database identity.
EntityManager.detach() method is cascaded to entities referenced by this entity if the attribute cascade=ALL or cascade=DETACH are used (check out cascading tutorial).
Example
The Entity
@Entity
public class Employee {
@Id
@GeneratedValue
private long id;
private String name;
private String dept;
.............
}
Persisting and loading
public class ExampleMain {
public static void main(String[] args) throws Exception {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("example-unit");
try {
persistEntity(emf);
loadEntity(emf);
} finally {
emf.close();
}
}
private static void persistEntity(EntityManagerFactory emf) throws Exception {
Employee e = new Employee();
e.setName("Jackie");
e.setDept("Account");
System.out.println("-- Persisting entity --");
System.out.println(e);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(e);
e.setDept("Admin");
//after commit entity will become detached
em.getTransaction().commit();
em.close();
//this will not be synchronized to database
e.setDept("IT");
}
private static void loadEntity(EntityManagerFactory emf) {
System.out.println("-- Loading entities --");
EntityManager em = emf.createEntityManager();
List<Employee> entityAList = em.createQuery("Select t from Employee t")
.getResultList();
entityAList.forEach(System.out::println);
em.close();
}
} Output-- Persisting entity -- Employee{id=0, name='Jackie', dept='Account'} -- Loading entities -- Employee{id=1, name='Jackie', dept='Admin'}
As seen above, the changes which are made to Employee entity after the transaction commit, are not synchronized to the database.
Using detach() method
public class ExampleMain2 {
public static void main(String[] args) throws Exception {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("example-unit");
try {
persistEntity(emf);
loadEntity(emf);
} finally {
emf.close();
}
}
private static void persistEntity(EntityManagerFactory emf) throws Exception {
Employee e = new Employee();
e.setName("Jackie");
e.setDept("Account");
System.out.println("-- Persisting entity --");
System.out.println(e);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(e);
//need flush before detaching so changes made so far will
//be synchronized to the database
em.flush();
//manually detaching
em.detach(e);
//this will not synchronized to the database
e.setDept("Admin");
em.getTransaction().commit();
em.close();
}
private static void loadEntity(EntityManagerFactory emf) {
System.out.println("-- Loading entities --");
EntityManager em = emf.createEntityManager();
List<Employee> entityAList = em.createQuery("Select t from Employee t")
.getResultList();
entityAList.forEach(System.out::println);
em.close();
}
} Output-- Persisting entity -- Employee{id=0, name='Jackie', dept='Account'} -- Loading entities -- Employee{id=1, name='Jackie', dept='Account'}
As seen above, changes made to Employee entity after invoking detach() are not synchronized to the database.
Example ProjectDependencies and Technologies Used: - hibernate-core 5.2.8.Final: The core O/RM functionality as provided by Hibernate.
Implements javax.persistence:javax.persistence-api version 2.1 - h2 1.4.193: H2 Database Engine.
- JDK 1.8
- Maven 3.3.9
|