병합
준영속 상태의 엔티티를 다시 영속 상태로 변경하려면 병합을 사용하면 된다. merge()
메소드는 준영속 상태의 엔티티를 받아서 그 정보로 새로운 영속 상태의 엔티티를 반환한다.
준영속 병합 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class ExamMerge {
static EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaTest");
public static void main(String[] args) {
Member member = createMember("memberA", "회원A"); // 1
member.setUsername("회원명 변경"); // 준영속 상태 2
mergeMember(member); // 3
}
static Member createMember(String id, String username) {
//== 영속성 컨텍스트1 시작 ==//
EntityManager em1 = emf.createEntityManager();
EntityTransaction tx1 = em1.getTransaction();
tx1.begin();
Member member = new Member();
member.setId(id);
member.setUsername(username);
em1.persist(member);
tx1.commit();
em1.close();
//== 영속성 컨텍스트1 종료 ==//
return member;
}
static void mergeMember(Member member) {
//== 영속성 컨텍스트2 시작 ==//
EntityManager em2 = emf.createEntityManager();
EntityTransaction tx2 = em2.getTransaction();
tx2.begin();
Member mergeMember = em2.merge(member);
tx2.commit(); // 4
//준영속 상태
System.out.println("member = " + member.getUsername());
//영속상태
System.out.println("mergeMember = " + mergeMember.getUsername());
System.out.println("em2 contains member = " + em2.contains(member)); //false
System.out.println("em2 contains mergeMember = " + em2.contains(mergeMember)); //true
em2.close();
//== 영속성 컨텍스트2 종료 ==//
}
}
- member 엔티티는 createMember() 메소드의 영속성 컨텍스트1에서 영속 상태 였지만 메소드가 종료되고 준영속 상태가 되었다.
- 준영속 상태에서 값을 변경하였기 때문에 변경감지가 동작하지 않아 실제 데이터 베이스에서 값이 변경되지 않는다.
- mergeMember() 메소드에서 member가 영속성 컨텍스트2에 영속 상태로 병합된다.
- 이때 member 값을 통해 새로운 mergeMember를 생성하게 되고 트랜잭션을 커밋할 때 변경감지를 통해 update 쿼리가 발생된다.
Merge 동작 방식
- merge()를 실행한다.
- 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티를 조회한다. 2.1. 만약 1차 캐시에 엔티티가 없으면 데이터 베이스에서 엔티티를 조회하고 1차 캐시에 저장한다.
- 조회한 영속 엔티티(mergeMember)에 member 엔티티의 값을 채워 넣는다.
- mergeMember를 반환한다.
비영속 병합
병합은 비영속 엔티티도 영속 상태로 만들 수 있다.
1
2
3
Member member = new Member();
Member newMember = em.merge(member); // 비영속 병합
tx.commit();
이 경우 파라미터로 넘어온 식별자로 엔티티를 조회할 수 없게 되는데 이때는 새로운 엔티티를 생성하여 병합한다.
정리
merge()
메서드는 준영속 상태의 엔티티를 다시 영속 상태로 변경해 준다. 하지만 이때 파라미터로 전달받은 엔티티를 영속상태로 변경하는 것이 아닌 영속 상태의 새로운 엔티티를 생성하여 반환해 준다. 그로 인해 파라미터로 전달 받은 엔티티는 여전히 준영속 상태로 남아있게 된다.
Comments powered by Disqus.