문제가 발생한 코드
상황
코치의 스케쥴을 업데이트하는 로직에서 Entity의 equals와 hashCode를 재정의하지 않아 List의 contains 메서드가 항상 false인 문제가 발생했다.
요약
equals와 hashCode를 재정의하지 않으면 어떤 문제가 발생하는지 알아본다.
또한, JPA의 Entity에서 equals와 hashCode를 재정의하지 않으면 어떻게 동작하는지 알아본다.
원인
위 문제는 equals를 재정의하지 않아 생긴 문제였다.
List 내의 Schedule들은 모두 비영속 상태이므로 JPA와 상관없이 순수 자바 로직 문제이다.
contains 메서드는 내부적으로 .equals() 동등 비교를 진행한다.
내부 요소 중 인자로 받은 값과 .equals() 비교를 진행했을 때 true인 객체가 하나라도 있다면 contains()는 true를 반환한다.
hashCode를 반드시 같이 재정의해줘야 할까?
위 경우 hash 값을 사용하지 않는 Collection을 사용했기 때문에 hashCode를 재정의하지 않아도 문제가 없었다. 그러나 Schedule 클래스는 언제든 hash 값을 사용하는 Collection(HashSet, HashMap, HashTable)에서 사용될 수 있다. 그러므로 equals와 hashCode를 항상 같이 재정의하는게 좋다.
참고로, hash 값을 사용하는 Collection(HashMap, HashSet, HashTable)은 객체가 논리적으로 같은지 비교(=equals)할 때 아래 그림과 같은 과정을 거친다.
hashCode 메서드의 리턴 값이 일치하는지 먼저 판단하고, 일치한다면 equals 메서드를 검증한다. hashCode -> equals 순으로 검증해 모두 true로 판단해야 비로소 논리적으로 같은 값으로 판단한다.
JPA Entity에서의 equals와 HashCode
JPA에서는 기본적으로 Entity의 식별자가 같으면 동일하다고 판단한다. 자세한 내용은 아래 블로그를 참고하자.
Entity의 equals와 hashCode를 재정의해도 될까?
Hibernate 공식 문서에서도 Entity equals와 hashCode를 재정의하라고 나와있다.
4.3. Implementing equals() and hashCode()
새로 생성한 Entity의 경우 id값을 할당받지 않았으니 문제가 발생할 수 있다. 그러니 id를 제외한 비즈니스 키(business key)로 equals와 hashCode를 재정의하는 것이 좋다.
We recommend implementing equals() and hashCode() using Business key equality.
'Programming > Java' 카테고리의 다른 글
package-info.java란 (0) | 2023.07.02 |
---|---|
Optional (0) | 2022.07.01 |
컨트롤러는 상태를 가지면 안된다. (0) | 2022.03.03 |
자바 추상클래스와 인터페이스 (0) | 2021.10.02 |