준영속 엔티티란?
영속성 컨텍스트가 더는 관리하지 않는 엔티티를 말한다.
영속 상태로 DB에 저장된 적이 있는, 식별자가 기존재하는 엔티티이다.
Book book = new Book();
book.setId(param.getId());
여기서 book은 새로운 객체이다. 하지만 기존의 식별자를 가지고 있다.
이러한 경우에는 준영속 엔티티로 볼 수 있다.
준영속 엔티티는 JPA가 관리를 하지않아 객체 내의 값을 수정해도 DB에 업데이트가 일어나지 않는다.
준영속 엔티티를 수정하는 방법
그러면 이미 영속성이 끊어진 준영속 엔티티로 어떻게 DB에 업데이트를 일으킬 수 있을까?
- 변경 감지 기능 (Dirty Checking) 사용
- 병합 (merge) 사용
변경 감지 기능 사용
@Transactional
void update(Member member) { // member: 파라미터로 넘어온 준영속 상태의 엔티티
Member findMember = em.find(Member.class, member.getId()); // 영속성이 동일한 있는 엔티티를 새로 조회
findMember.setName(member.getName()); // 데이터 수정
}
- 준영속 엔티티의 식별자 값으로 영속성 엔티티를 조회한다.
- 데이터를 수정한다.
- 커밋 시점에 자동으로 update 쿼리가 실행된다.
병합 사용
@Transactional
void update(Member member) {
Member mergedMember = em.merge(member);
}
- 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티를 조회한다.
- 1차 캐시에 엔티티가 없으면 DB에서 엔티티를 조회하고 1차 캐시에 저장한다.
- 조회한 영속 엔티티에 엔티티의 값을 각각 전부 교체해 채워넣는다.
- 영속 상태인 mergedMember를 반환한다.
- 커밋 시점에 자동으로 update 쿼리가 실행된다.
변경 감지 기능과 병합의 차이점
변경 감지 기능은 원하는 속성만 선택해 변경할 수 있지만, 병합을 사용하면 모든 속성이 변경된다.
이게 위험한 이유는 병합할 엔티티 내에 값이 없는 컬럼이 있으면 null로 업데이트가 된다.
실무에서는 보통 변경가능한 데이터만 노출하기 때문에 상기된 이유로 병합을 사용하는 것이 오히려 번거롭다고 한다.
변경 감지 기능을 잘 활용하는 방법
- 컨트롤러에서 어설프게 엔티티를 생성하지 말자.
- 받아온 폼 데이터를 바탕으로 컨트롤러에 엔티티를 생성하면 불필요한 set메소드가 많아진다.
- 꼭 필요한 데이터만 파라미터로 전달, 파라미터가 많다면 DTO로 서비스 단에 전달하자.
- 트랜잭션이 있는 서비스 계층에서 영속상태의 엔티티를 조회하고, 엔티티의 데이터를 변경하자.
'Spring > 이론' 카테고리의 다른 글
프록시 형태 별 차이 (인터페이스 VS 클래스) (0) | 2024.01.04 |
---|---|
[JPA] 응답 값으로 DTO를 전달해야 하는 이유 (0) | 2023.10.04 |
동적 쿼리 VS 정적 쿼리 차이, 예시 (0) | 2023.09.06 |
[JPA] JPQL fetch join 페치 조인 (0) | 2023.08.02 |
[JPA] JPQL 경로 표현식 (0) | 2023.08.02 |