- JPA Merge, Dirty Check2023년 06월 06일
- starryeye
- 작성자
- 2023.06.06.:52
이번 포스트에서 다룰 주제는 JPA 의 Merge, Dirty Check 에 대해서이다.
merge() 에 대해서 데이터 업데이트 용도로 쓰면 위험하므로 권장하지 않는 방법이다.
왜 이런말이 나왔을까..위 코드는 Spring Data Jpa 의 SimpleJpaRepository 의 Save 메서드 정의 부분이다.
Jpa 를 잘 모르고 사용하면..
데이터 업데이트를 위해서 비/준영속 상태의 엔티티로
save 를 호출해버린다면 merge 를 호출한 상황이 발생하기 때문이다.
참고>
isNew() 에 대해서.. 알아보자
JPA 식별자 생성 전략이 @GenerateValue 이면, save() 호출 시점에 식별자가 없으므로
새로운 엔티티로 인식해서 persist() 로 로직이 흘러간다..
하지만..
JPA 식별자를 Application layer 에서 만들어주는 형태이면..
save() 호출 시점에 식별자가 존재해버리므로.. merge() 가 동작해버린다.
merge() 는 DB 에 해당 식별자가 존재하는지 확인하는 쿼리를 날리고
식별자가 없으면 새로운 엔티티로 인지한다. (매우 비효율적)
따라서, PK 직접 할당 방식을 채택 할 경우에는..
Persistable 인터페이스를 Entity 가 상속받도록 하여 isNew() 메서드를 재정의 하는 방법으로 생각해야한다.
isNew() 기본 로직은 아래와 같다.
- 식별자가 객체이면 null 일 경우 true
- 식별자가 primitive type 이면 0 일 경우 true
데이터 업데이트는 영속상태의 엔티티에 대해서 변경감지를 이용
이유는 merge() 를 사용하면 비/준영속 상태의 엔티티에 대해서 merge() 를 호출하면
비/준영속 엔티티의 값으로 모두 교체된 새로운 영속 엔티티가 반환되고..
이는 commit 시에 변경감지가 동작하여 최악의 경우 모두 null 로 업데이트 되는 상황이
생길 수 있기 때문이다.
그럼 merge() 는 언제 사용하는 것인가..
단순히 비/준영속 상태의 엔티티를 영속상태의 엔티티로 변경할 때 사용하는 것이다. (매우 특수한 상황)
(주의, 데이터 변경 없어야함)
참고>
JPA 의 변경감지 기본 전략은 "모든" 필드를 업데이트 하는 것이다.
(수정된 데이터만 동적으로 업데이트 하려면 Hibernate DynamicUpdate 전략 이용)
-> 보통 컬럼이 30개 이상 되면 DynamicUpdate 방식이 빠르다.
(그러나, 30개 이상이면 책임이 적절히 분리 안되었을 가능성이 높다.)
'Spring > DB, Cache 연동' 카테고리의 다른 글
JPA 변경 감지와 플러시 (0) 2023.06.15 JPA Entity Default Constructor (1) 2023.06.07 Spring Cache Annotation (0) 2023.06.04 Spring Data Redis (0) 2023.06.03 Spring 의 DB 연동 기술 히스토리 요약 (0) 2023.03.10 다음글이전글이전 글이 없습니다.댓글