Home 6. 영속 객체의 라이프사이클
Post
Cancel

6. 영속 객체의 라이프사이클

01. 영속 객체의 라이프사이클 개요

영속 객체는 영속 컨텍스트와의 연관 상태에 따라 관리됨, 분리됨, 삭제됨 상태를 갖는다.

JPA는 영속 컨텍스트에 보관된 객체의 변경 내역을 추적한다. JPA의 영속 컨텍스트를 통해서 관리되는 상태의 영속 객체는 관리됨 상태를 갖는다. 이 시점에 트랜잭션 범위 안에서 변경하면 커밋 시점에 변경 내역을 DB에 반영한다.

EntityManager가 종료되면 영속 컨텍스트가 사라지고 이 시점에 영속 객체는 영속 컨텍스트와의 관계가 끊어진다. 이때 분리됨 상태가 된다.

remove() 메서드에 관리 상태의 객체를 전달하면 삭제됨 상태가 되고, 영속 객체가 삭제되면 트랜잭션 커밋 시점에 해당 데이터를 DB에서 삭제한다.

02. EntityManager#persist()와 관리 상태 객체

persist()를 이용해서 영속 컨텍스트에 엔티티 객체를 추가하면 해당 엔티티 객체는 관리 상태가 된다. 영속 컨텍스트는 엔티티 객체를 관리할 때 식별자를 기준으로 각 엔티티를 구분한다.

엔티티 객체 추가시 식별자 생성 방식에 따라 insert 쿼리가 실행되는 시점이 달라진다. 엔티티 클래스의 id 필드가 MySQL의 auto_increment 칼럼에 매핑되어 있는 경우 auto_increment는 데이터를 삽입할 때 자동으로 값이 증가하므로 persist() 메서드에 객체를 전달하면 그 시점에 insert 쿼리를 실행한다.

테이블을 이용해서 식별자를 생성하는 경우에는 persist()에 엔티티를 추가할 때 식별자를 구하기 위한 쿼리가 실행된다. (엔티티 객체를 DB에 insert X) 그리고 실제 엔티티 객체를 DB에 저장하기 위한 insert 쿼리는 트랜잭션을 커밋하는 시점에 실행된다.

엔티티 객체를 추가할 때 주의할 점은 트랜잭션 범위에서 실행하지 않으면 엔티티를 DB에 추가하는 insert 쿼리를 실행하지 않는다는 점이다.

1
2
3
4
5
6
7
8
em.transaction().begin();

User user = new User("asd@asd.com", "user", new Date());
em.persist(user);

user.changeName("user02"); //user 객체는 관리 상태이므로 변경 내역을 추적한다.

em.getTransaction().commit(); // user의 변경 내역도 함께 반영됨

EntityManager.persist()로 엔티티 객체를 영속 컨텍스트에 추가하는데 이는 캐시에 엔티티 객체가 보관된다는 것을 뜻한다. persist()로 저장한 엔티티 객체의 식별자를 이용해서 find()로 엔티티 객체를 구하면 persist()로 저장한 객체를 리턴한다.

03. EntityManager#find()와 관리 상태 객체

find()로 구한 객체도 영속 컨텍스트에 보관되어 관리 상태가 된다. 관리 상태의 영속 객체는 트랜잭션 범위에서 상태가 바뀌면 트랜잭션을 커밋하는 시점에 변경 내역을 반영하기 위한 update 쿼리를 실행한다.

find()로 로딩한 객체는 영속 컨텍스트에 보관되므로 동일 식별자를 갖는 엔티티를 다시 find()로 구하면 select 쿼리를 다시 실행하지 않고 영속 컨텍스트에 보관된 엔티티 객체를 리턴한다.

04. 분리 상태 객체

영속 컨텍스트에 보관된 영속 객체는 EntityManager가 종료되면 분리 상태가 된다. 분리 상태가 되면 객체의 상태를 변경해도 DB에 반영되지 않는다.

05. EntityManager#merge()로 분리 상태를 관리 상태로 바꾸기

merge()를 사용하면 분리 상태의 엔티티를 다시 관리 상태로 만들 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
EntityManager em = EMF.createEntityManager();
User user = null;

try{
  user = em.find(User.class, "madvirus@madvirus.net");
}finally{
  em.close();
}
//이 시점엔 분리 상태
user.changeName("Choi, Beom Kyun");

EntityManager em2 = EMF.createEntityManager(0;
try{
  em2.getTransactin().begin();
  em2.merge(user);    //user는 다시 관리 상태가 됨
  em2.getTransaction().commit();  //변경내역 반영
}catch(Exception e) {
  em2.getTransaction().rollback();
  throw e;

}finally{
  em2.clos()l
}

06. 삭제 상태 객체

remove() 메서드에 관리 상태 영속 객체를 전달하면 삭제 상태로 바뀐다. 그리고 트랜잭션 커밋 시점에 delete 쿼리를 실행해서 삭제 상태에 해당하는 해당 데이터를 DB에서 삭제한다.

remove()로 삭제 상태로 바뀐 엔티티를 다시 merge()에 전달하면 Exception이 발생한다.

This post is licensed under CC BY 4.0 by the author.