JPA 및 최대 절전 모드를 사용할 때 어떻게 동등하고 해시 코드를 구현 해야하는지

StackOverflow https://stackoverflow.com/questions/1638723

문제

모델 클래스의 평등과 해시 코드는 최대 절전 모드에서 어떻게 구현되어야합니까? 일반적인 함정은 무엇입니까? 대부분의 경우 기본 구현이 충분합니까? 비즈니스 키를 사용한다는 의미가 있습니까?

게으른 페치, ID 생성, 프록시 등이 고려 될 때 모든 상황에서 일하기가 매우 어렵다는 것이 나에게 있어야합니다.

도움이 되었습니까?

해결책

Hibernate는 언제 / 어떻게 재정의하는지에 대한 멋지고 긴 설명이 있습니다. equals() / hashCode() 안에 선적 서류 비치

그것의 요점은 당신의 엔티티가 Set 또는 인스턴스를 분리 / 부착하려는 경우. 후자는 그다지 일반적이지 않습니다. 전자는 일반적으로 다음을 통해 가장 잘 처리됩니다.

  1. 기본 equals() / hashCode() 비즈니스 키에서 - 예를 들어 객체 (또는 적어도 세션) 수명 동안 변경되지 않는 고유 한 속성 조합.
  2. 위의 불가능한 경우 기본 equals() / hashCode() 기본 키에서 설정된 경우 객체 ID / System.identityHashCode() 그렇지 않으면. 그만큼 중요한 여기에는 당신이 필요하다는 것입니다 다시로드 새로운 엔티티가 추가되어 지속되어 지속되었습니다. 그렇지 않으면 엔티티가 현재와 일치하지 않는 버킷에 할당 될 수 있기 때문에 이상한 행동으로 끝날 수 있습니다 (궁극적으로 오류 및 / 또는 데이터 손상이 발생 함). hashCode().

다른 팁

나는 받아 들여진 대답이 정확하다고 생각하지 않습니다.

원래 질문에 답하기 위해 :

대부분의 경우 기본 구현이 충분합니까?

대답은 그렇습니다. 대부분의 경우 그렇습니다.

당신은 단지 무시하면됩니다 equals() 그리고 hashcode() 엔티티가 a Set (매우 흔합니다) 그리고 엔티티는 최대 절전 모드 세션에서 분리 된 후 다시 부착 될 것입니다.

허용 된 답변은 메소드가 어느 하나 조건은 사실입니다.

엔티티가 게으른 하중을 통해로드되면 기본 유형의 인스턴스가 아니지만 javassist에 의해 생성 된 동적으로 생성 된 하위 유형이므로 동일한 클래스 유형에 대한 확인이 실패하므로 사용하지 마십시오.

if (getClass() != that.getClass()) return false;

대신 사용 :

if (!(otherObject instanceof Unit)) return false;

설명했듯이 좋은 관행입니다. Java 관행에서 동등한 구현.

같은 이유로, 직접 필드에 액세스하는 것은 근본 값 대신 작동하지 않고 널 리턴 할 수 있으므로 속성에 비교를 사용하지 말고 기본 값을로드하기 위해 트리거 할 수 있으므로 getters를 사용하십시오.

최고 equals/hashCode 구현은 a를 사용할 때입니다 독특한 비즈니스 키.

비즈니스 키는 모든 것에 따라 일관성이 있어야합니다 엔티티 상태 전환 (과도, 부착, 분리, 제거)는 평등을 위해 ID에 의존 할 수없는 이유입니다.

또 다른 옵션은 사용으로 전환하는 것입니다 UUID 식별자, 응용 프로그램 논리에 의해 할당되었습니다. 이렇게하면 UUID를 사용할 수 있습니다. equals/hashCode 엔티티가 플러시되기 전에 ID가 할당되므로.

엔티티 식별자를 사용할 수도 있습니다 equals 그리고 hashCode, 그러나 그것은 항상 당신이 항상 똑같이 반환해야합니다. hashCode 엔티티 해시 코드 값이 모든 엔티티 상태 전환에서 일관되도록하는 값. 체크 아웃 이 주제에 대한 자세한 내용은이 게시물입니다.

그래, 어렵다. 내 프로젝트에서 해시 코드는 객체의 ID에 의존합니다. 이 솔루션의 문제점은 데이터베이스에 의해 ID가 생성되므로 객체가 아직 지속되지 않은 경우 어느 것도 작동하지 않는다는 것입니다. 제 경우에는 거의 모든 경우에 객체가 바로 지속되기 때문에 견딜 수 있습니다. 그 외에는 훌륭하게 작동하며 구현하기 쉽습니다.

당신이 재정의된다면 equals, 계약을 이행해야합니다.

  • 대칭
  • 반사
  • 전이
  • 일관된
  • 비 널

그리고 무시합니다 hashCode, 계약에 따라 의존합니다 equals 구현.

Joshua Bloch (Collection Framework의 디자이너)는 이러한 규칙을 강력히 촉구했습니다.

  • 항목 9 : 항상 해시 코드를 재정의하면

이 계약을 따르지 않을 때는 의도하지 않은 효과가 있습니다. 예를 들어 List.contains(Object o) 잘못 되돌릴 수 있습니다 boolean 일반 계약이 이행되지 않은 가치.

Hibernate 5.2의 문서에서는 상황에 따라 해시 코드를 구현하고 전혀 동등하게 구현하고 싶지 않을 수 있습니다.

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/hibernate_user_guide.html#mapping-model-pojo-equalshashcode

일반적으로 동일한 세션에서로드 된 두 개의 객체는 데이터베이스에서 동일하면 (해시 코드를 구현하지 않고) 동일하면 동일합니다.

두 번 이상 세션을 사용하는 경우 복잡해집니다. 이 경우 두 객체의 동등성은 평등 방법 구현에 따라 다릅니다.

또한 Equals-Method가 처음으로 개체를 지속하는 동안 만 생성 된 ID를 비교하면 문제가 발생합니다. 평등이 불려질 때 아직 거기에 없을 수도 있습니다.

여기에는 아주 좋은 기사가 있습니다. 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 
}

}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top