Frage

Wie soll in Hibernate modellieren Klasse equals und hashcode umgesetzt werden? Was sind die häufigsten Fallen? Ist die Standardimplementierung gut genug für die meisten Fälle? Gibt es einen Sinn Geschäftsschlüssel zu benutzen?

Es scheint mir, dass es ziemlich schwierig ist, es richtig zu machen in jeder Situation zu arbeiten, wenn lazy fetching, id Generation, Proxy, etc. berücksichtigt werden.

War es hilfreich?

Lösung

Hibernate hat eine schöne und lange Beschreibung, wann / wie equals() / hashCode() in Dokumentation

Der Kern ist es Ihnen nur darum kümmern müssen, wenn Ihr Unternehmen Teil einer Set sein wird oder wenn Sie vorhaben, werden Abnehmen / seine Instanzen anzubringen. Letzteres ist nicht so üblich. Ersteres wird in der Regel am besten behandelt über:

  1. Gründend equals() / hashCode() auf einem Geschäftsschlüssel - z.B. eine einzigartige Kombination von Eigenschaften, die bei dem Objekt sich ändern, wird nicht (oder zumindest Session) Lebensdauer.
  2. Wenn die oben nicht möglich ist, Basis equals() / hashCode() auf Primärschlüssel, wenn es gesetzt und Objektidentität / System.identityHashCode() anders. Der wichtig Teil hier ist, dass Sie auf reload Ihr Set nach neuer Einheit wurde hinzugefügt, und beharrte; sonst können Sie mit seltsamen Verhalten am Ende (letztlich zu Fehlern und / oder Datenverfälschungen führen), weil Ihr Unternehmen auf einen Eimer zugeordnet werden kann, nicht seinen aktuellen hashCode() entspricht.

Andere Tipps

Ich glaube nicht, dass die akzeptierte Antwort korrekt ist.

die ursprüngliche Frage zu beantworten:

  

Ist die Standardimplementierung gut genug für die meisten Fälle?

Die Antwort ist ja in den meisten Fällen ist es.

Sie müssen nur equals() und hashcode() außer Kraft setzen, wenn das Unternehmen in einer Set verwendet werden (was sehr häufig) und wird das Unternehmen von abgenommen werden und anschließend wieder an, Hibernate-Sitzungen (das ist eine seltene Verwendung von Hibernate).

Die akzeptierte Antwort zeigt an, dass die Methoden außer Kraft gesetzt werden müssen, wenn entweder Bedingung wahr ist.

Wenn ein Unternehmen durch verzögertes Laden geladen wird, ist es nicht eine Instanz des Basistypen, sondern eine dynamisch generierte Subtyp von Javassist erzeugt, so dass eine Überprüfung derselben Klasse wird fehlschlagen, so nicht verwenden:

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

statt:

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

, die auch eine gute Praxis, wie erläutert auf Implementierung entspricht in Java Practices .

aus dem gleichen Grund, Felder Zugriff direkt, möglicherweise nicht und null zurück, anstelle des Basiswerts, so nicht verwenden Vergleich zu den Eigenschaften, aber die Getter verwenden, da sie auslösen könnten, die zugrunde liegenden Werte zu laden.

Die beste equals / hashCode Implementierung ist, wenn Sie ein einzigartiger Business-Schlüssel rel="nofollow .

Der Geschäftsschlüssel sollte in allen Entitätsstatus im Einklang Übergänge (transient, angebracht, freistehend, entfernt), das ist, warum Sie nicht auf id für die Gleichstellung verlassen können.

Eine weitere Möglichkeit ist durch die Anwendung zur Verwendung von UUID Identifikatoren , zugewiesen wechseln Logik. Auf diese Weise können Sie die UUID für den equals / hashCode verwenden, da die ID zugewiesen wird, bevor die Einheit gespült wird.

Sie können sogar die Einheits-Identifikation für equals und hashCode verwenden, aber das erfordert, dass Sie immer den gleichen hashCode Wert zurück, so dass Sie sicher, dass das Unternehmen hashCode Wert ist in allen Unternehmen Zustandsübergänge konsistent. Schauen Sie sich diesen Beitrag für mehr zu diesem Thema .

Ja, es ist schwer. In meinem Projekt gleich und hashCode beide verlassen sich auf die ID des Objekts. Das Problem dieser Lösung ist, dass keiner von ihnen arbeitet, wenn das Objekt noch nicht beibehalten worden, wie die ID von Datenbank erzeugt wird. In meinem Fall, da in fast allen Fällen Objekte erträglich sind sofort anhielt. Other than that, es funktioniert super und ist einfach zu implementieren.

Wenn Sie geschehen equals außer Kraft zu setzen, stellen Sie sicher, dass Sie erfüllen ihre Verträge: -

  • SYMMETRY
  • REFLEKTIERENDES
  • TRANSITIVE
  • CONSISTENT
  • NON NULL

Und hashCode außer Kraft setzen, wie der Vertrag über equals Umsetzung verlassen.

Joshua Bloch (Designer Collection Framework) dringend aufgefordert, diese Regeln befolgt werden.

  • Artikel 9: Immer überschreiben hashCode, wenn Sie überschreiben equals

Es gibt ernsthafte unbeabsichtigte Wirkung, wenn Sie diese Verträge nicht folgen. List.contains(Object o) könnte falsch boolean Wert zurückgeben zum Beispiel als der allgemeine Vertrag nicht erfüllt werden.

In der Dokumentation von Hibernate 5.2 es sagt, dass Sie nicht hashCode implementieren möchten und gleich überhaupt -. Je nach Situation

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

Im Allgemeinen zwei Objekte aus der gleichen Sitzung geladen werden gleich sein, wenn sie in der Datenbank gleich sind (ohne hashCode Implementierung und gleich).

Es wird kompliziert, wenn Sie mit zwei oder mehr Sitzungen. In diesem Fall hängt die Gleichheit zweier Objekte auf equals-Methode Umsetzung.

Darüber hinaus werden Sie in Schwierigkeiten geraten, wenn Ihre equals-Methode IDs vergleicht, die nur erzeugt werden, während ein Objekt zum ersten Mal persistierenden. Sie könnten noch nicht da sein, wenn equals genannt wird.

Es ist sehr schön Artikel hier: https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/persistent-classes-equalshashcode.html

eine wichtige Linie aus dem Artikel Zitiert:

  

Wir empfehlen die Umsetzung equals () und hashCode () mit Business-Schlüssel   Gleichberechtigung. Geschäftsschlüssel Gleichheit bedeutet, dass die Methode equals ()   vergleicht nur die Eigenschaften, die die Geschäftsschlüssel, einen Schlüssel bilden, die   würde unser Beispiel in der realen Welt (einen natürlichen Kandidaten identifizieren   key):

Vereinfacht

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 
}

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top