영속성 컨텍스트
- 엔티티를 관리하는 논리적인 개념
- 어플리케이션과 DB 사이에서 객체를 보관하는 가상의 DB 같은 역할
- 엔티티를 메모리에 저장, 엔티티의 생명주기 관리, 엔티티와 DB 간의 작업 캐시해서 처리
준영속 엔티티
- 영속성 컨텍스트가 더는 관리하지 않는 엔티티 (DB에 한 번 갔다와서 식별자 존재)
- 수정하는 방법 - 변경 감지 기능, 병합(merge) 사용
변경 감지 기능 사용
@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한다.
findItem.setPrice(itemParam.getPrice()); //데이터를 수정한다.
}
- 영속성 컨텍스트에서 엔티티를 다시 조회한 후에 데이터 수정
- 트랜잭션 안에서 엔티티 다시 조회, 변경할 값 선택 -> 트랜잭션 커밋 시점에 변경 감지 (Dirty Checking)이 동작해서 DB에 UPDATE SQL 실행
Dirty Checking
- 상태 변경 검사
- JPA에서는 트랜잭션이 끝나는 시점에 변화가 있는 모든 엔티티 객체를 데이터베이스에 자동으로 반영
- JPS에서는 엔티티를 조회하면 해당 엔티티의 조회 상태를 스냅샷으로 만듦
- 트랜잭션이 끝나는 시점에 이 스냅샷과 비교해서 변경이 있으면 Update query 발생
- dirty checking 대상은 영속성 컨텍스트가 관리하는 엔티티에만 적용
- 준영속, 비영속 상태의 엔티티는 dirty checking 대상에 포함되지 않음
병합 사용
@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
Item mergeItem = em.merge(itemParam);
}
병합은 준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능
- 준영속 엔티티의 식별자 값으로 영속 엔티티 조회
- 영속 엔티티의 값을 준영속 엔티티의 값으로 모두 교체 (병합)
- 트랜잭션 커밋 시점에 변경 감지 기능이 동작해서 데이터베이스에 UPDATE SQL 실행
병합의 단점
- 병합을 사용하면 모든 속성 변경 (특정 속성 변경 불가능)
- 병합시 값이 없으면 null로 업데이트할 위험
결론
준영속 엔티티를 변경할 때는 변경 감지를 사용하자..!
- controller에서 엔티티 생성 금지 -> 파라미터나 DTO 이용해 서비스 계층에 데이터 전달
- 트랜잭션이 있는 서비스 계층에서 영속 상태의 엔티티를 조회하고 엔티티의 데이터 직접 변경
- 트랜잭션 커밋 시점에 변경 감지 실행
'backend > springboot' 카테고리의 다른 글
Session을 사용한 로그인 구현 (0) | 2024.04.16 |
---|---|
Cookie를 사용한 로그인 구현 (0) | 2024.04.16 |
로그인 구현 방법 세팅 (0) | 2024.04.16 |
도메인 모델 패턴, 트랜잭션 스트립트 패턴 (0) | 2024.04.04 |
99클럽 코테 스터디 1일차 TIL - springboot 의존성 주입 (0) | 2024.04.01 |