[JPA] Select했는데 Update 쿼리가 같이 생성될 경우

BlackBean99·2022년 8월 21일
1

JPA

목록 보기
2/3

JPA Entity 설계를 하면서 꼭 겪는 문제
바로 내가 원하지 않는 쿼리가 같이 날라가는 문제!
그런 문제들은 꼭 공부를 해봐야 겠죠!

Entity에서 find 문을 실행하면
orderRepository.findById(id)

이런식으로 select와 함께 update가 같이 날라갑니다!

이게 저번 포스팅때 이야기한 Dirty Checking과 관련이 있을까요?

JPA를 사용하면 대부분 Hibernate를 사용할텐데한 트랜젝션 범위에서 Entity를 조회하면 조회 시점의 Entity 복사본을 만듭니다

Entity 원본과 복사본의 비교는 객체의 equals로 판단하지 않고 각 컬럼들이 같은지 비교를 한다.

칼럼 하나 비교에 사용되는 이 함수는 해당 객체의 equals 메소드를 호출한다.

Java에서는 객체의 equals를 override하지 않으면 레퍼런스(주소) 비교를 합니다.
같은 값을 가져도 신규 생성된 객체와 기존 객체와 비교하면 false가 발생합니다

클래스에 @EqualsAndHashCode를 달아준다 = equals를 override 한다.
-> Dirty Checking이 발생하지 않는다.

다른 방법으로 막을 수 없나요?

@Embedded 로 선언된 객체는 필드가 아닌 Entity의 영역을 확대시킨 것이라, 실제 비교를 @Embedded로 선언된 객체가 아닌 @Embedded 클래스 내부의 필드들이 대상입니다.

  • Member 클래스의 equals를 사용하지 않고 필드값에 대해 각각 equals 를 사용합니다.

Period 의 경우 객체형 필드이지만
불변 객체(Immutable type)라서 이미 equals가 구현되어 있다.

복사본이 생겨도 동일한 객체가 생성돼서 Dirty Checking하지 않는다.

Dirty Checking 제외 항목

  • LocalDateTime, LocalTime 역시 동일한 객체가 생성되지 않으므로 DirtyChecking 대상이 아니다.

  • @OneToMany, @OneToOne, @ManyToOne등으로 선언된 객체. Entity이기 때문에 필드 비교 대상이 아니다.

결론

  • 가변 객체(mutanble types) 를 Entity 필드로 사용할 경우 DirtyChecking의 남용을 막기 위해 equals를 Override한다.
  • 안그러면 단순 조회도 DirtyChecking이 발생한다.

Reference

profile
like_learning

0개의 댓글