2010-12-08 4 views
42

Ich möchte überprüfen, ob Unternehmen in einem Sammelelement (@OneToMany oder @ManyToMany) eines anderen Unternehmens ist:Sollte ich equals() Methoden in JPA-Entitäten schreiben?

if (entity2.getEntities1().contains(entity1)) { } 
+0

auf diese Frage, die Motivation zu erarbeiten: [ 'Collection.contains (JpaEntity someobject)'] (http://docs.oracle.com/javase/7/docs/api/java /util/Collection.html#contains(java.lang.Object)) benötigt eine sinnvolle 'JpaEntity.equals (...)' Methode. – Abdull

+0

Siehe auch http://StackOverflow.com/a/39827962/548473 (Spring-Data-Jpa-Implementierung) – GKislin

Antwort

104

Nicht unbedingt. Es gibt drei Optionen:

  • nicht überschreiben - so werden Sie mit Instanzen arbeiten. Dies ist in den Fällen sinnvoll, in denen Sie mit den Sammlungen nur mit Entitäten arbeiten, die an die Sitzung angehängt sind (und somit garantiert dieselbe Instanz sein). Dies ist (für mich) in vielen Fällen der bevorzugte Weg, da weniger Code und weniger Überlegung beim Überschreiben erforderlich ist.

  • übersteuern hashCode() und equals() mit einem Geschäftsschlüssel. Dies kann eine Teilmenge von Eigenschaften sein, die die Entität identifizieren. Zum Beispiel könnte für einen User ein guter Geschäftsschlüssel der username oder der email sein. Dies wird als gute Praxis angesehen.

  • übersteuern hashCode() und equals() nur über das ID-Feld. Dies ist in einigen Fällen sinnvoll, insbesondere wenn Sie einen manuell zugewiesenen Bezeichner (wie eine UUID) haben. Es ist auch in Ordnung, wenn Ihre Entität niemals in eine Sammlung geht. Aber für transiente Entitäten (ohne Kennung), die in Sammlungen gehen, verursacht es Probleme, so vorsichtig mit dieser Option. Als Seanizer notiert - Sie sollten es vermeiden. Im Allgemeinen immer, wenn Sie wirklich wissen, was Sie tun (und dokumentieren es vielleicht)

See this article für weitere Details. Beachten Sie auch, dass equals() und hashCode() gebunden sind und beide mit genau den gleichen Feldern implementiert werden sollten.

+2

nette Antwort (+1) –

+0

ok, ich habe dies in Entity1 hinzugefügt und jetzt funktioniert es: public boolean gleich (Objekt andere) { if (this.getClass () .isInstance (andere)) { return this.id == ((UserEntity) andere) .id; } sonst { Rückgabe false; } } öffentliche int hashCode() { \t \t return id; } – j2j

+1

also wählten Sie die am wenigsten bevorzugte Option;) Achten Sie auf Nebenwirkungen. – Bozho

2

dass der einzige Weg ist. Sie können versuchen, Pojomatic Bibliothek, die die harte Arbeit für Sie erledigt.

12

Ja, Sie sollten definieren equals() und hashcode() Methoden entsprechen, aber Sie sollten die ID Teil entweder nie sein lassen. (Siehe this recent answer of mine in einer ähnlichen Frage)

+0

Ich habe von Zeit zu Zeit verwendet Gleichheits-und Hashcode mit der ID nur überschrieben, und es hat gut funktioniert. Es stimmt, ich habe die Anwendungsfälle und die Tatsache, dass ich nicht mit transienten Entitäten arbeiten werde, berücksichtigt. Also würde ich nicht genau 'nie' sagen: – Bozho

+0

Ich * würde * niemals sagen, weil es nicht möglich ist, vorübergehende und verbundene Entitäten zu vergleichen, ist ein No-Go für mich, aber ich verstehe die Einfachheit Ihres Ansatzes (solange Sie kennen die Nachteile) –

+0

Das hängt davon ab, wann Sie Ihre IDs zuweisen. Wenn es Geschäftsschlüssel gibt, möchte ich keine anderen IDs haben. So ist der Punkt strittig. –

5

Wir neigen dazu, lassen IDE hashCode() und equals() für uns generieren. Sei aber vorsichtig. Wenn Sie diese Methoden für JPA-Entitäten generieren. Einige Versionen von equals() Kontrollen für Klassenidentität

// ... inside equals() - wrong approach for Entities (cause of generate proxies) 
if (o == null || this.getClass() != o.getClass()) { 
     return false; 
} 
// ... 

dies Ihre Sammlungen mit einigen JPA Bibliotheken brechen würde, da diese Bibliotheken Proxies Ihre Entitäten (Unterklassen) erstellen, wie zum Beispiel MyGreatEntity_$$_javassist_7 in dem Ruhezustand.

In Entitäten immer Unterklassen in equals() zulassen.

0

Ja, Sie sollten!

Wenn Sie nicht dem Standard Java.lang.Objectequals und hashCode Implementierung außer Kraft setzen:

@Entity(name = "Book") 
public class Book implements Identifiable<Long> { 

    @Id 
    @GeneratedValue 
    private Long id; 

    private String title; 

    //Getters and setters omitted for brevity 
} 

der merge Betrieb wird eine andere Objektinstanz zurückgeben und die Gleichheit Vertrag wird auf as explain in this post gebrochen werden.

Der beste Weg ist es, einen Business-Schlüssel zu verwenden, wie folgt aus:

@Entity 
public class Book implements Identifiable<Long> { 

    @Id 
    @GeneratedValue 
    private Long id; 

    private String title; 

    @NaturalId 
    private String isbn; 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (!(o instanceof Book)) return false; 
     Book book = (Book) o; 
     return Objects.equals(getIsbn(), book.getIsbn()); 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(getIsbn()); 
    } 

    //Getters and setters omitted for brevity 
} 

Sie können auch die Kennung für Gleichheit verwenden, sondern daran, dass die hashCode Umsetzung sollte immer den gleichen Wert zurück, wie in den gleichen erklärt schreiben, dass ich bereits erwähnt:

@Entity 
public class Book implements Identifiable<Long> { 

    @Id 
    @GeneratedValue 
    private Long id; 

    private String title; 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (!(o instanceof Book)) return false; 
     Book book = (Book) o; 
     return Objects.equals(getId(), book.getId()); 
    } 

    @Override 
    public int hashCode() { 
     return 31; 
    } 

    //Getters and setters omitted for brevity 
} 
Verwandte Themen