답변:
Hibernate는 재정의하는 방법을 때 /의 좋은 긴 설명이 equals()
/ hashCode()
에 문서
요점은 엔터티가 a의 일부가 Set
되거나 인스턴스를 분리 / 연결할 경우에만 걱정할 필요가 있다는 것입니다. 후자는 그다지 일반적이지 않습니다. 전자는 일반적으로 다음을 통해 가장 잘 처리됩니다.
equals()
/ hashCode()
비즈니스 키 - (적어도, 세션이나) 수명을 객체 동안 변화하지 않을 속성의 예를 들면 독특한 조합.equals()
/ hashCode()
차 키는 IF 그것의 세트와 객체의 정체성 / System.identityHashCode()
그렇지. 여기서 중요한 부분은 새 엔티티가 추가되고 지속 된 후에 세트 를 다시로드 해야한다는 것입니다 . 그렇지 않으면 엔티티가 현재 hashCode()
.refresh()
무엇 을하는 것 입니까? Set
계약 을 준수하는 엔터티가 어떻게 잘못된 버킷에 들어가게됩니까 (해시 코드 구현이 충분히 좋다고 가정).
Set.contains(entity)
하면 false
. get () / put () / 등도
받아 들여진 대답이 정확하다고 생각하지 않습니다.
원래 질문에 답하려면 :
대부분의 경우 기본 구현이 충분합니까?
대부분의 경우 그렇습니다.
당신은 대체해야 equals()
하고 hashcode()
엔티티가 사용됩니다 경우 Set
(이 매우 일반적이다) 와 엔티티가 부착 재 이후에서 분리 될 것입니다 (최대 절전 모드의 드문 사용되는) 세션을 최대 절전 모드.
허용되는 대답은 두 조건 중 하나 가 참이면 메서드를 재정의해야 함을 나타냅니다 .
가장 좋은 equals
/ hashCode
당신이 사용할 때 구현은 고유 한 비즈니스 키를 .
비즈니스 키는 모든 엔터티 상태 전환 (일시적, 연결됨, 분리됨, 제거됨)에서 일관성이 있어야합니다. 그렇기 때문에 동일성을 위해 ID에 의존 할 수 없습니다.
또 다른 옵션은 애플리케이션 로직에 의해 할당 된 UUID 식별자 사용으로 전환하는 것 입니다. 이렇게 하면 엔티티가 플러시되기 전에 ID가 할당되기 때문에 equals
/에 UUID를 사용할 수 있습니다 hashCode
.
equals
및 hashCode
에 대해 엔티티 식별자를 사용할 수도 있지만, hashCode
모든 엔티티 상태 전환에서 엔티티 hashCode 값이 일관되도록 항상 동일한 값을 반환 해야합니다. 이 주제에 대한 자세한 내용은이 게시물을 확인하십시오 .
BaseEntity
그 문제에 대해 다시 생각하지 마십시오. 그것은 DB를 측면에 공간이 조금 걸리지 만 그 가격 당신에게 :) 안락을위한 더 나은 급여
지연로드를 통해 엔티티가로드되면 기본 유형의 인스턴스가 아니지만 javassist에 의해 생성 된 동적으로 생성 된 하위 유형이므로 동일한 클래스 유형에 대한 검사가 실패하므로 다음을 사용하지 마십시오.
if (getClass() != that.getClass()) return false;
대신 다음을 사용하십시오.
if (!(otherObject instanceof Unit)) return false;
이는 Java Practices에서 같음 구현에 설명 된 것처럼 좋은 방법이기도합니다 .
같은 이유로 필드에 직접 액세스하면 기본 값 대신 작동하지 않고 null을 반환 할 수 있으므로 속성에 대한 비교를 사용하지 말고 getter를 사용하여 기본 값을로드하도록 트리거 할 수 있습니다.
예, 어렵습니다. 내 프로젝트에서 equals와 hashCode는 둘 다 객체의 ID에 의존합니다. 이 솔루션의 문제점은 ID가 데이터베이스에 의해 생성되기 때문에 오브젝트가 아직 지속되지 않은 경우 둘 다 작동하지 않는다는 것입니다. 제 경우에는 거의 모든 경우에 객체가 즉시 유지되기 때문에 허용됩니다. 그 외에는 훌륭하게 작동하고 구현하기 쉽습니다.
Hibernate 5.2의 문서에서는 상황에 따라 hashCode 및 equals를 구현하고 싶지 않을 수도 있다고 말합니다.
일반적으로 동일한 세션에서로드 된 두 개체는 데이터베이스에서 동일하면 동일합니다 (hashCode 및 equals를 구현하지 않음).
두 개 이상의 세션을 사용하면 복잡해집니다. 이 경우 두 객체의 동등성은 동등 메소드 구현에 따라 다릅니다.
또한 equals-method가 처음으로 객체를 지속하는 동안 만 생성 된 ID를 비교하는 경우 문제가 발생할 수 있습니다. equals가 호출 될 때 아직 거기에 없을 수도 있습니다.
여기에 아주 좋은 기사가 있습니다 : https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/persistent-classes-equalshashcode.html
기사에서 중요한 내용을 인용 :
비즈니스 키 동등성을 사용하여 equals () 및 hashCode ()를 구현하는 것이 좋습니다. 비즈니스 키 동등성은 equals () 메서드가 실제 세계에서 인스턴스를 식별하는 키 (자연 후보 키) 인 비즈니스 키를 형성하는 속성 만 비교 함을 의미합니다.
간단히 말해서
public class Cat {
...
public boolean equals(Object other) {
//Basic test / class cast
return this.catId==other.catId;
}
public int hashCode() {
int result;
return 3*this.catId; //any primenumber
}
}
을 재정의 한 경우 equals
계약을 이행했는지 확인하십시오.
hashCode
계약은 equals
구현에 의존하므로 재정의하십시오 .
Joshua Bloch (컬렉션 프레임 워크 설계자)는 이러한 규칙을 준수 할 것을 강력하게 촉구했습니다.
이러한 계약을 따르지 않으면 의도하지 않은 심각한 결과가 발생합니다. 예를 들어 일반 계약이 이행되지 않아 List#contains(Object o)
잘못된 boolean
값을 반환 할 수 있습니다 .