준영속 상태란? 

1. 영속 상태의 엔티티가 영속성 컨텍스트에서 분리된것을 준영속 상태라고 한다.

2. 영속성 컨텍스트가 제공하는 기능을 사용하지 못함 

 

준영속 상태 만드는 법 

- em.detach(entity)

  • 특정엔티티만 준영속 상태로전환 
  • 1차 캐시에서 빠진다고 생각하면 쉬움 

- em.clear()

  • 영속성 컨텍스트 완전히 초기화 
  • 테스트 케이스 작성시 사용 

- em.close()

  • 영속성 컨텍스트를 종료 

 

준영속 컨텍스트가 더는 관리하지 않는 엔티티를 말한다. 

  • DB에 한번 갔다온 엔티티 
  • DB에 한번 저장되어 식별자가 존재하는 객체 
    • 이러한 준영속 엔티티는 JPA가 관리를 하지않기 때문에 객체를 수정해도 DB에 Update가 일어나지 않는다. 

 

 

준영속 엔티티를 수정하는 2가지 방법 

1. 변경 감지 기능 사용 

Service 계층에 메서드를 추가한다. 

@Transactional
	void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
		Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한다.
		findItem.setPrice(itemParam.getPrice()); //데이터를 수정한다. 
	}
  • 영속성 컨텍스트에서 해당ID를 다시 조회한 후 데이터 수정한다. 
  • 조회한 findItem은 영속상태이다. 
  • 이러한 영속상태의 데이터를 수정하면 커밋 시점에 내부적으로 flush가 발생해 Dirty Checking이 일어난다. 

즉 변경감지기능 사용은 준영속 엔티티의 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(itemParam);
}

 

병합의 단점 

하는 일은 병합과 변경 감지 기능이 비슷한데 병합에는 단점이 있다. 

em.merge(item) 이런식으로 파라미터에 객체를 통채로 보낸다. 그러므로 특정 속성을 변경 할수 없고 객체의 모든 속성을 변경해야한다. 

변경감지는 속성 값 하나씩 다 수정하기 때문에 가격 부분을 제외하고 수정하면 된다. 

병합(merge)를 사용할 경우 객체 자체를 넘기기 때문에 객체에 price가 null이면 수정되서 반환된 객체의 price도 null로 수정되어 문제가 발생할 수 있다. 

모든 속성을 변경한는게 왜 단점이냐 라고 질문할 수 있는데 예시를 들어보겠다. 

'- 코딩 공부' 카테고리의 다른 글

OSIV와 성능 최적화  (0) 2023.11.08
API 개발 고급 - 컬렉션 조회 최적화  (1) 2023.11.01
JPA - 주문 도메인 개발  (0) 2023.09.10
JPA 실전  (0) 2023.09.03
JPA - 객체지향 쿼리 언어1  (0) 2023.07.31

+ Recent posts