[java] JPA와 Hibernate를 사용할 때 어떻게 같고 해시 코드를 구현해야 하는가

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

게으른 가져 오기, ID 생성, 프록시 등을 고려할 때 모든 상황에서 올바르게 작동하는 것이 매우 어려운 것 같습니다.



답변

Hibernate는 재정의하는 방법을 때 /의 좋은 긴 설명이 equals()/ hashCode()문서

요점은 엔터티가 a의 일부가 Set되거나 인스턴스를 분리 / 연결할 경우에만 걱정할 필요가 있다는 것입니다. 후자는 그다지 일반적이지 않습니다. 전자는 일반적으로 다음을 통해 가장 잘 처리됩니다.

  1. 내놓고 equals()/ hashCode()비즈니스 키 – (적어도, 세션이나) 수명을 객체 동안 변화하지 않을 속성의 예를 들면 독특한 조합.
  2. 위에서 불가능베이스의 경우 equals()/ hashCode()차 키는 IF 그것의 세트와 객체의 정체성 / System.identityHashCode()그렇지. 여기서 중요한 부분은 새 엔티티가 추가되고 지속 된 후에 세트 를 다시로드 해야한다는 것입니다 . 그렇지 않으면 엔티티가 현재 hashCode().

답변

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

원래 질문에 답하려면 :

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

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

당신은 대체해야 equals()하고 hashcode()엔티티가 사용됩니다 경우 Set(이 매우 일반적이다) 엔티티가 부착 재 이후에서 분리 될 것입니다 (최대 절전 모드의 드문 사용되는) 세션을 최대 절전 모드.

허용되는 대답은 조건 중 하나 가 참이면 메서드를 재정의해야 함을 나타냅니다 .


답변

가장 좋은 equals/ hashCode당신이 사용할 때 구현은 고유 한 비즈니스 키를 .

비즈니스 키는 모든 엔터티 상태 전환 (일시적, 연결됨, 분리됨, 제거됨)에서 일관성이 있어야합니다. 그렇기 때문에 동일성을 위해 ID에 의존 할 수 없습니다.

또 다른 옵션은 애플리케이션 로직에 의해 할당 된 UUID 식별자 사용으로 전환하는 것 입니다. 이렇게 하면 엔티티가 플러시되기 전에 ID가 할당되기 때문에 equals/에 UUID를 사용할 수 있습니다 hashCode.

equalshashCode에 대해 엔티티 식별자를 사용할 수도 있지만, hashCode모든 엔티티 상태 전환에서 엔티티 hashCode 값이 일관되도록 항상 동일한 값을 반환 해야합니다. 이 주제에 대한 자세한 내용은이 게시물을 확인하십시오 .


답변

지연로드를 통해 엔티티가로드되면 기본 유형의 인스턴스가 아니지만 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를 구현하고 싶지 않을 수도 있다고 말합니다.

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

일반적으로 동일한 세션에서로드 된 두 개체는 데이터베이스에서 동일하면 동일합니다 (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 
}

}