728x90
반응형
728x90
변경 감지(Dirty Checking)
- JPA (Java Persistence API)는 Java에서 객체와 관계형 데이터베이스 간의 매핑을 제공하는 API
- JPA가 엔티티 객체의 상태를 자동으로 추적하고, 객체의 상태가 변경되었는지 여부를 감지하는 기능
- EntityManager의 flush() 메서드를 호출할 때 작동
동작 방식
- 상태 추적
- JPA는 엔티티의 최조 상태를 스냅샷으로 저장
- 스냅샷은 1차 캐시에 저장되고 엔티티의 원본 상태를 나타냄
- 변경 감지
- EntityManager의 flush() 메서드가 호출되면 JPA는 현태 엔티티 상태와 스냅샷을 비교
- 엔티티 객체의 필드가 변경된 것이 감지되면 JPA는 SQL UPDATE 쿼리로 변환
- 자동 동기화
- flush() 메서드가 호출되면, JPA는 감지된 모든 변경 사항을 데이터베이스에 반영
- 트랜잭션이 커밋될 때도 자동으로 발생
장단점
- 장점
- 직접 쿼리를 작성하거나 상태를 수동으로 동기화할 필요가 없으므로 코드가 더 간결해짐
- 데이터베이스와 자바 객체 간의 상태 일관성을 자동으로 유지할 수 있음
- 트랜잭션이 커밋될 때 변경된 내용이 자동으로 데이터베이스에 반영되므로 트랜잭션 관리 용이
- JPA는 변경된 데이터만 데이터베이스에 반영 -> 전체 엔티티를 업데이트하는 것보다 성능이 좋음
- 단점
- 변경 감지 기능이 활성화되면 엔티티의 모든 필드에 대해 변경 여부를 체크 -> 엔티티가 많은 경우 성능 저하
- 엔티티의 상태가 자동으로 동기화되어 언제 어떤 상태를 데이터베이스에 반영할지 세밀하게 제어하기 어려움
성능 최적화
- @DynamicUpdate 어노테이션 사용 시 변경된 필드만 update 쿼리에 포함시켜 성능 향상
병합(Merge)
- 관리되고 있지 않은 엔티티(준영속) 객체를 데이터베이스와 동기화하는 기능
- 일반적으로 다른 세션이나 트랜잭션에서 가져온 엔티티 객체를 데이터베이스에 반영할 때 사용
동작 방식
- EntityManager의 merge() 호출
- 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티를 조회
- 1차 캐시에 엔티티가 없으면 데이터베이스에서 엔티티를 조회하고, 1차 캐시에 저장
- 조회한 영속 엔티티에 파라미터로 넘어온 값을 채워 넣음
- 복사된 영속 엔티티 반환
장단점
- 장점
- detached(준영속) 상태로 존재하던 엔티티를 쉽게 데이터베이스와 동기화할 수 있음
- 직접 merge() 메서드를 호출하여 언제 데이터를 동기화할지 명시적으로 제어할 수 있음
- 병합을 통해 변경할 엔티티의 범위를 명확히 지정할 수 있음
- 단점
- 복잡한 객체 그래프와 연관된 엔티티들을 처리할 때 복잡성이 증가 -> 새 엔티티를 반환하기 때문에 원본 엔티티와 일관성 유지가 어려움
- 대량의 엔티티를 병합할 때 성능 문제가 발생 -> merge() 호출 시 데이터베이스에 많은 업데이트 발생 가능
- 의도치 않은 상태 변경이나 동기화 문제
병합 전략
- MERGE: merge()를 사용한 방법으로 엔티티의 모든 필드를 업데이트
- UPDATE: 변경된 필드만 업데이트
- REPLACE: 기존 엔티티를 삭제하고 새로운 엔티티로 대체
준영속 상태 (Detached state)
- 엔티티 객체가 데이터베이스와의 연결이 끊어졌지만, 이전에 EntityManager에 의해 관리되었던 상태
영속 엔티티(Persistent Entity)
- EntityManager에 의해 관리되고 있는 데이터베이스와 연결된 상태
- EntityManager를 통해 데이터베이스에서 엔티티를 가져오는 경우
준영속 엔티티(Detached Entity)
- 데이터베이스와 연결되어 EntityManager에 관리되었던 상태 -> 현재는 연결이 끊어짐
- EntityManager를 통해 데이터베이스에서 가져온 엔티티의 정보로 새로운 객체를 만든 경우
- 객체의 정보는 EntityManager가 관리하는 영속 엔티티와 같지만 별도의 객체가 됨
- EntityManager에 의해 관리되지 않아 변경 감지가 일어나지 않음
준영속 엔티티 수정
- 준영속 상태의 엔티티를 다시 영속성 컨텍스트에서 조회하여 EntityManager가 관리하는 영속 엔티티를 수정 -> 변경 감지
- merge() 사용-> 반환값이 영속 엔티티
사용 구분
- 변경 감지: 같은 트랜잭션 내에서 엔티티를 수정할 때 주로 사용
- 병합: 분리된 엔티티를 다시 영속 상태로 만들 때 사용
성능
- 변경 감지는 메모리 상의 비교만으로 작동 가능
- 병합 사용 시 무조건 데이터베이스의 조회가 발생
병합 사용 시 문제점
- merge() 호출 시 모든 필드가 파라미터로 넘어온 준영속 엔티티 값으로 바뀜
- 일부 변경이 없어야 할 필드가 null이 되거나 의도치 않은 값 변경이 있을 수 있음
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 강의 | 김영한 - 인프런 (inflearn.com) 강의 내용 참고
728x90
'백엔드 > Spring' 카테고리의 다른 글
[Spring] 영속성 컨텍스트 (Persistence Context) (0) | 2024.09.08 |
---|---|
[Spring] JPA 개요 (1) | 2024.09.07 |
[Spring] 스프링 트랜잭션 전파 Propagation (0) | 2024.09.05 |
[Spring] 스프링 트랜잭션 (0) | 2024.09.04 |
[Spring] MyBatis (1) | 2024.09.01 |