준영속 상태란?
- 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached)된 것
- 영속성 컨텍스트가 제공하는 기능을 사용 못함
준영속 상태로 만드는 방법
- em.detach(entity) 특정 엔티티만 준영속 상태로 전환
- em.clear() 영속성 컨텍스트를 완전히 초기화
- em.close() 영속성 컨텍스트를 종료
준영속 엔티티란?
영속성 컨텍스트가 더는 관리하지 않는 엔티티.
임의로 만들어낸 엔티티라도 기존 식별자를 가지고 있는 경우
(JPA가 식별 할 수 있는 id를 가지고 있음)
준영속 엔티티를 수정하는 2가지 방법
- 변경 감지 기능 사용
- 병합( merge ) 사용
변경 감지 기능 사용
@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한다.
findItem.setPrice(itemParam.getPrice()); //데이터를 수정한다.
}
영속성 컨텍스트에서 엔티티를 다시 조회한 후에 데이터를 수정하는 방법
트랜잭션 안에서 엔티티를 다시 조회, 변경할 값 선택 트랜잭션 커밋 시점에 변경 감지(Dirty Checking)이 동작해서 데이터베이스에 UPDATE SQL 실행
병합 사용
병합 : 기존에 있는 엔티티
병합은 준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능이다.
@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
Item mergeItem = em.merge(item);
}
병합 동작 방식
- 준영속 엔티티의 식별자 값으로 영속 엔티티를 조회한다.
- 영속 엔티티의 값을 준영속 엔티티의 값으로 모두 교체한다.(병합한다.)
- 트랜잭션 커밋 시점에 변경 감지 기능이 동작해서 데이터베이스에 UPDATE SQL이 실행
1. merge() 를 실행한다. merge(member)
2. 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티를 조회한다.
2-1. 만약 1차 캐시에 엔티티가 없으면 데이터베이스에서 엔티티를 조회하고, 1차 캐시에 저장한다.
3. 조회한 영속 엔티티( mergeMember )에 member 엔티티의 값을 채워 넣는다. (member 엔티티의 모든 값
을 mergeMember에 밀어 넣는다. 이때 mergeMember의 “회원1”이라는 이름이 “회원명변경”으로 바
뀐다.)
4. 영속 상태인 mergeMember를 반환한다.
※ 주의
변경 감지 기능을 사용하면 원하는 속성만 선택해서 변경할 수 있지만,
병합을 사용하면 모든 속성이 변경된다.
병합시 값이 없으면 null 로 업데이트 할 위험도 있다. (병합은 모든 필드를 교체한다.)
따라서 엔티티를 변경할 때는 병합 대신 변경 감지를 사용하자.
참조
책 - 자바 ORM 표준 JPA 프로그래밍
인프런 - 실전! 스프링 부트와 JPA 활용1
'웹개발 > Spring' 카테고리의 다른 글
[JPA] 양방향 연관관계 (0) | 2020.01.19 |
---|---|
[JPA] 엔티티 매핑 ⭐️ @Entity, @Table, @Column, @Id (0) | 2020.01.17 |
[JPA] 플러시란? Flush (0) | 2020.01.17 |
[JPA] 영속성 컨텍스트란? Entity Manager (0) | 2020.01.16 |
DI (Dependency Injection) 의존 주입 (0) | 2020.01.15 |