JPA - equals() und hashcode()

Nun, Entities sollten sich nur anhand der ID unterscheiden.
Wenn man keine ID hat (nicht persitiert), schraenkt das enorm ein.
Leider muss man meistens auch mit dem Dingern arbeiten koennen bevor sie persistiert wurden…
Man stelle sich zwei Person Entitaeten vor, selber Name, vielleciht auhc noch selbes Geburtsdatum, etc., es sind aber wirklich 2 unterschiedlcihe Menschen…

Weil das nunmal Semantisch falsch ist.
Schlimmer wird es nur noch dadurch, dass man mal so und mal so die Gleichheit festlegt, da liegt der Hase im Pfeffer.

zunächst: frühe Id ist ganz nett (edit: selbstbestimmt, nicht automatisch), ob aus Anwendung oder DB ist mir auch egal, dagegen habe ich nichts zu sagen,
aber Verwendung in equals/ hashCode?

welche Anwendungsfälle bedenkst du/ andere hierbei, allgemein für equals/ hashCode für Entities?

mir fallen aktuell 2-3 Dinge ein:

Sammeln von Objekten in HashSet:
eine Liste von 100 Entities Typ A liegt vor, die jeweils beliebig auf einen Entity Typ B verweisen
→ alle 100 B in ein Set eintragen, am Ende sind es vielleicht nur 20, die weiter zu bearbeiten sind, da auf gleiche verwiesen wird

Caches:
bei mir HashMap Id->Entity, andere Einträge haben aus Sparsamkeit nur die Id vorhanden, Entity dazu muss geholt werden

Doppelten-Prüfung mit neu angelegten Entities, allgemein Suche mit Eingabedaten:
mache ich persönlich nicht auf diese Weise, da oft dann auch nur nach Teilmenge der Attribute, nicht gesetze Felder zu berücksichtigen,
dazu ist mehr Arbeit nötig


  • equals und hashCode rein auf Id:
    Sammeln: effizient

Cache:
würde nicht helfen, sollte die HashMap die Entity selber als Key haben?
kommt allgemein durchaus vor, etwa beim HashSet, aber wie wollte man hier suchen,
zu jeder Such-Id erst ein Entity-Objekt erstellen, mit neuer Id!, dann die Id ändern!! und dann suchen?

Suche: absolut nicht hilfreich


  • equals und hashCode auf Attribute:
    Sammeln:
    etwas weniger effizient, wobei man in equals noch bei gesetzen Ids diese für schnelles Feststellen von Gleichheit/ Ungleichheit verwenden kann,
    aber hashCode zwingend auf Attribute ist langsamer

Cache: egal wenn man eh die Id nehmen muss

Suche: begrenzt nützlich, zumindest denkbar, aber setze ich zumindest wie gesagt so kaum ein


  • gar kein equals und hashCode:
    Sammeln: ideal,
    wenn man annimmt dass es alle Entities je nur einmal gibt,
    speziell für Hibernate-kontrollierte Objekte normalerweise der Fall,
    bei Transfer-Objekten nicht ganz so leicht, was mich auch oft wieder zu Ids und Caches treibt :wink:

Cache: egal wenn man eh die Id nehmen muss

Suche: absolut nicht hilfreich

Ich komm da nicht mit

**Man stelle sich zwei Person Entitaeten vor, selber Name, vielleciht auhc noch selbes Geburtsdatum, etc., es sind aber wirklich 2 unterschiedlcihe Menschen… **

Wenn schon persistent - Datenbank PK vergleichen (genau das will man ja mit einer solchen Entity)

Wenn noch nicht persistent - was hilft bei dem Problem dann eine neue, softwareseitige ID die sofort bei der Erzeugung auf so ein flüchtiges Ding draufgeklebt wird? Dann kannst du ja anhand verschiedener IDs gar nicht entscheiden, ob die nicht doch „den gleichen Mensch“ darstellen - also doch die Attribute anschauen…

Ich suchte ja ein Beispiel dafür, wie man so eine ID tatsächlich verwenden kann/muss - und man gleichzeitig die Attribute ignoriert.

Weil das nunmal Semantisch falsch ist.
Schlimmer wird es nur noch dadurch, dass man mal so und mal so die Gleichheit festlegt, da liegt der Hase im Pfeffer.

Ich habe 2 Arten (mit ohne DB-PK, Attribute) du hast drei (mit ohne DB-PK, Attribute, softwareID) - also wo ist der Vorteil?

Semantisch bedeutet deine SoftwareID doch nur, dass irgendwo in deiner komplexen Software zwei Objekte erzeugt wurden. Und was nutzt diese „semantische“ Information?

Mal angenommen, du hast zwei Personen ohne Datenbank-PK, die in allen Attributen übereinstimmen - ein Duplikat, noch nicht persistent. Was nützt es, wenn da eine zusätzliche ID draufklebt? Für mich als Programmierer würde es doch völlig egal sein, ob das zwei Referenzen auf ein einziges oder zwei Referenzen auf zwei verschiedene Objekte wäre?

Wie schon gesagt, ich blick da nicht ganz durch. Bräuchte mal ein konkretes Beispiel für den Nutzen.

[quote=Bleiglanz]Wenn schon persistent - Datenbank PK vergleichen (genau das will man ja mit einer solchen Entity)

Wenn noch nicht persistent - was hilft bei dem Problem dann eine neue, softwareseitige ID die sofort bei der Erzeugung auf so ein flüchtiges Ding draufgeklebt wird? Dann kannst du ja anhand verschiedener IDs gar nicht entscheiden, ob die nicht doch „den gleichen Mensch“ darstellen - also doch die Attribute anschauen…[/quote]
Sieh es mal so:
Wenn man das Persistenzframework die IDs vergeben laesst, hat man das Problem dass man je nachdem ob schon persistiert wurde oder nicht anders damit umgehen muss → komplex & fehleranfaellig, verkruepelte equals Methode
Wenn man das die Domaene machen laesst → simpel, weil die ID nur eindeutig sein muss, sonst nix.

Verstehe nicht ganz was du mit „Beispiel“ meinst.

Jedes Projekt dass die IDs durch die Persistenz vergibt ist ein Beispiel, die haben alle verkruepelte equals Methoden und inkonsistenzes verhalten von equals und hashcode, man muss dort immer unterscheiden ob schon persistiert wurde (ID zum vergleich nutzen) oder nicht (Felder fuer Vergleiche nutzen), komplex, fehleranfaellig, dazu kommt dass die Domaene eigentlich schon eindeutigkeit erfordert, dies aber erst durch Persistierung errreicht wird.
Die vergabe von IDs durch das Persistenzframework ist das konkrete Problem dass weitere Probleme verursacht.

Natuerlich kann dir das NICHT egal sein, weil:

  • versuchst du 2 transiente Entitaeten zu vergleichen und nutzt nur die ID (wird von der Persistenz gesetzt), sind 2 transiente Entitaeten immer gleich da ID == null → Fehler
  • versuchst du 2 transiente Entitaeten zu vergleichen und nutzt ID falls schon persistiert wurde, falls noch transient nutzt du die anderen Felder → komplexe und „kaputte“ equals und hashcode Methoden, in HashSet etc. willst du das nicht einfuegen sonst entstehen Fehler

Wenn die Domaene die IDs vergibt:

  • equals & hashcode funzen immer gleich, sind simpler aufgebaut, es kann dir vollkommen wurscht sein ob schon persistiert wurde oder nicht, es wird immer gleich verfahren, equals und hashcode sind nicht kaputt, dafuer verhalten sie sich immer gleich, kein Problem mit HashSet etc. pp.

Vielleicht wird es ja jetzt klarer :slight_smile:

Na ja, ich sehe ja schon den Punkt (Collections, Caches, etc.) - bin aber nicht so ganz überzeugt.

Klar sind equals/hashcode simpler und einfacher bei softwareIDs (gerade bei vielen Attributen ist das oft riesig und wirr, weil sich das ja auf Beziehungen fortsetzt), ok das wär ein Argument. Performance vielleicht nicht so wirklich, die paar Nanos…

- versuchst du 2 transiente Entitaeten zu vergleichen und nutzt nur die ID (wird von der Persistenz gesetzt)
macht keiner, wäre grob falsch

** versuchst du 2 transiente Entitaeten zu vergleichen und nutzt ID falls schon persistiert wurde, falls noch transient nutzt du die anderen Felder -> komplexe und “kaputte” equals und hashcode Methoden, in HashSet etc. willst du das nicht einfuegen sonst entstehen Fehler**

Schon klar. Aber trotzdem: zwei POJOs mit voller Attributübereinstimmung die sich nur durch eine künstliche ID unterscheiden und die noch nicht in die DB persistiert wurden - so etwas als “verschieden” zu behandeln muss ein Fehler im Datenmodell sein. Dann gäbe es keinen PK, dann wären zwei Zeilen in der DB ununterscheidbar.

Aber wenn ich so überlege: die extrem simplen equals/hashcodes haben natürlich was für sich. Nur scheint halt die korrekte Erzeugung solcher softwareIDs nicht gerade einfach zu sein…

Gibt es da noch keine Frameworks, die das automatisch erledigen… - wäre doch ideal für einen JPA-Provider das via Annotation zu machen?

[quote=Bleiglanz]Aber wenn ich so überlege: die extrem simplen equals/hashcodes haben natürlich was für sich. Nur scheint halt die korrekte Erzeugung solcher softwareIDs nicht gerade einfach zu sein…
[/quote]
Gibt es ja shcon, sind aber eben alle an die Persistenz gekoppelt (JPA bzw Hiebrnate eben), die zaubern auch nicht, ist nicht kompliziert, Hibernate/EclipseLink initialisieren zB. auch beim start die naechst hoehere ID.
Naja, Hibernate/EclipseLink etc. kennen mehrere wege das zu machen

  • das ORM erzeugt die ID
  • die DB erzeugt die ID (Sequences, ID)

Ist wirklich einfach falls es keine verteilte Anwendung ist, einen IdGenerator der beim Start der Anwendung die hoechste ID aus der DB liest und diese dann um 1 inkrementiert, fertig.
Dann ist das auch keine ORM/Persistenzkiste mehr, sondern wird von der Domaene gemacht.

[quote=maki]Natuerlich kann dir das NICHT egal sein, weil:

  • versuchst du 2 transiente Entitaeten zu vergleichen und nutzt nur die ID (wird von der Persistenz gesetzt), sind 2 transiente Entitaeten immer gleich da ID == null -> Fehler
  • versuchst du 2 transiente Entitaeten zu vergleichen und nutzt ID falls schon persistiert wurde, falls noch transient nutzt du die anderen Felder -> komplexe und “kaputte” equals und hashcode Methoden, in HashSet etc. willst du das nicht einfuegen sonst entstehen Fehler

Wenn die Domaene die IDs vergibt:

  • equals & hashcode funzen immer gleich, sind simpler aufgebaut, es kann dir vollkommen wurscht sein ob schon persistiert wurde oder nicht, es wird immer gleich verfahren, equals und hashcode sind nicht kaputt, dafuer verhalten sie sich immer gleich, kein Problem mit HashSet etc. pp.[/quote]
    also auf ‘kaputte equals, Angst vor HashSet’ usw. kannst du doch langsam verzichten,

man muss natürlich einmal drüber nachdenken und hat dann etwas ineffizentiere und kompliziertere (und damit fehleranfälligere) Methoden, ja,
aber man kann doch nur davon ausgehen dass man es richtig macht, 95% des Programms sind noch komplizierter, soll man davor auch immer Angst haben?

mit hashCode() auf Attribute und equals()

else vergleiche Felder

hat man sichere Methoden für HashSets, keine Fehler bei normaler Verwendung möglich (*)


was ist mit dem Fall ‘2 transiente Entitaeten zu vergleichen und nutzt ID falls schon persistiert wurde, falls noch transient nutzt du die anderen Felder’?
hier legt man anscheinend mindestens eine Entity gerade neu an,
wenn man nach Attributen schaut hat man so die Möglichkeit, im HashSet Doppelte zu finden,

wird beim Anlegen blind eine neue Id vergeben, dann wird garantiert nichts im HashSet gefunden, wieso schaut man überhaupt nach,
jeder Eintrag für sich garantiert neu

das ist ein fachlicher/ programmlogischer Unterschied und eine viel größere Frage/ Fehlerquelle als Aufpassen sich an sauberes equals-Konzept zu halten?


was man mit einem neuen Objekt vor Speicherung, vor Id, machen will ist sicherlich eine Frage,
aber zumindest denkbar dass Attribute irgendeine Rolle spielen, irgendwie irgendwo mal zu einem Vergleich hilfreich sind,

JEDEM Objekt eine neue Id zuzuweisen schaltet einen gesamten Programmteil aus, Attribute spielen dann wirklich keine Rolle mehr,
dass man dann equals entsprechend baut ist klar, aber relativ kleiner Punkt, schließlich funktioniert auch equals nach Attributen so wenn Ids erstmal vergeben sind,

allein der Umstand, dass jedes neue Objekt sofort unique ist, nicht erkennbar ob bereits/ noch zu persistieren/ gleich etwas anderem oder nicht, ist doch für sich viel größere Frage?


(*) hashCode() auf Attribute kann böse reagieren auf Änderungen der Attribute zu beliebigen Zeitpunkt, das ist wahrlich noch ein bedeutendes Problem dabei,
unabhängig von der Frage der Id-Zuweisung am Anfang

Nein hat man nicht.

Wenn die Entitaeten persitiert werden nachdem sie in das HashSet eingefuegt wurden, aendern sich das ergenis von equals und hashcode, das HashSet „findet“ sie nicht mehr, man bekommt sie nie mehr raus.

quote=SlaterB;97618 hashCode() auf Attribute kann böse reagieren auf Änderungen der Attribute zu beliebigen Zeitpunkt, das ist wahrlich noch ein bedeutendes Problem dabei,
unabhängig von der Frage der Id-Zuweisung am Anfang[/quote]
Ebend :wink:

[quote=SlaterB;97618]wird beim Anlegen blind eine neue Id vergeben, dann wird garantiert nichts im HashSet gefunden, wieso schaut man überhaupt nach,
jeder Eintrag für sich garantiert neu[/quote]
Packe dochmal transiente und persistente Entitaeten ein ein HashSet/HashMap, totales Chaos droht, weil equals/hascode mal so und dann wieder mal so funktioniert…

Das Problem ist ja, dass sich die Definition von „Gleichheit“ aendert, je nachdem ob persitiert wurde oder nicht…

Der Ausweg ist IMHO ganz klar: IDs nicht von der Persistenz vergeben lassen, fertig.

Die Frage ob eine Entity schon eprsitiert ist oder nciht ist volllkommen irrelvant wenn es keinen Einfluss mehr hat (zB. auf equals/hashcode), die Frage an sich ist nur dadurch bedingt weil sich die Semantik beim ueblichen Vorgehen - naemlich IDs von der Persistenz erzeugen zu lassen - aendert.

Macht das die Domaene, ist es wieder wurscht ob persistent oder transient.
Dinge werden logischer, einfacher, konsistenter und man muss keine Angst mehr haben Standard Java Collection/Maps zu nutzen :slight_smile:

[QUOTE=maki]Nein hat man nicht.

Wenn die Entitaeten persitiert werden nachdem sie in das HashSet eingefuegt wurden, aendern sich das ergenis von equals und hashcode, das HashSet „findet“ sie nicht mehr, man bekommt sie nie mehr raus.
[/QUOTE]

hinsichtlich ‚equals mit Attributen‘, bei welchem konkreten Code soll das wie genau der Fall sein?

equals/ hashcode, welche ausschließlich die Attribute anschauen, ignorieren doch eben die Id vollkommen, was sollte die Persistierung bewirken?

die übliche leichte Optimierung

else vergleiche Felder

hashCode dabei gleichbleibend, funktioniert auch ohne Probleme?

edit: natürlich unter der Annahme dass man auch wirklich bei zwei Objekte mit gleichen Attributen eine Übereinstimmung finden will,
dass nicht letztlich 2 Objekte exakt gleichen Inhalt mit unterschiedlichen Ids in der DB landen,
bei solch beliebig Doppelten kann man ja schon selber eine laufende Nummer zur Unterscheidung vergeben oder sollte sich fragen ob die in ein Set kommen

dass ‚equals nur mit Id‘ ohne vorhandene Id nicht geht, nun das ist keine große Überraschung

Wenn die Identitaet eben nicht von den Attributen bestimmt werden soll, das ist bei allen Entities der Fall.

Das ist nett, aber eben im Falle von Entitaeten schlicht falsch.

Du und ich, wir sind unterschiedliche Meschnen, aber nicht weil wir andere Namen haben, ein anderes Geburtsdatum etc. pp.
Sondern schlicht weil du bist, und ich ich bin, wir sind einzigartig als Grundannahme.
Uebertrage dieses Beispiel mal auf Eineiige Zwillinge, selbes Geburtsdatum, selber Nachname, ja sogar exakte Uebereinstimmung bei der DNS!
Wenn die Eltern jetzt dieselben Vornamen fuer beide vergeben, ist es dann nur eine einzige Person?

Das ist das PROBLEM.
hashcode muss mit equals passen, equals == true → hashcode muss identisch sein.

Beispiel:
Du erzeugst eine transiente Entity, packst sie in ein HashSet.
Du aenderst nun einige Werte dieser transienten Entity… und nun?
Packst du die Entity nochmal in das HashSet, geht schon los mit dem Problemen… 2-mal dieselbe Entity drinnnen nur mit unterschiedlichen Werten?
Welche ist die „richtige“? :wink:
Pack dann nochmal die Entity in das rein HashSet nachdem sie persitiert wurde…

Egal wie man es dreht und wendet, die sematische Aenderung der Gleichheit je nachdem ob persitiert wurde oder nicht ist murks und erzeugt weitere Probleme!

Alles Versuche das mit trickreichen equals/hashcode Methoden in den Griff zu bekommen sind nur Kruecken oder haben erhebliche Einschraenkungen und erzeugen nunmal viel komplexitaet, weil es nur Workarounds fuer das eigentliche Problem sind:
Wie „Gleichheit“ definiert ist sollte sich nie aendern.
Das erreicht man NICHT indem man das Persitenzframework IDs vergeben laesst die zur Definition von „Gleichheit“ genutzt werden.

eben hieß es noch

was denn nun?

dass diese Methoden bei Änderung der Attribute nicht funktionieren ist ja nun allgemein bekannt,
betrittt alle Klassen der Welt, hat nichts mit Hibernate-Ids, Zeitpunkt der Zuweisung zu tun,
für den Anlegevorgang von Datenbank-Entities ist das auch nicht gerade üblich (obwohl das natürlich ein weites Feld ist)

ein neues Objekt wird mit befüllten Feldern angelegt, Punkt, da ändert sich nichts mehr (außer vielleicht noch der Id…),
aktuell ist hier nur die Frage interessant, ob ein Id-Feld befüllt wird oder nicht,
es bleibt dann auch ein und dasselbe Objekt, nicht ein zweites nun mit Id, das alte noch ohne

hinsichtlich dieser einen Frage, Id dazu oder nicht, funktionieren equals/hashcode auf Attributen, evtl. optimiert mit Id-Vergleich,
(spart nur Zeit, ändert nichts, unter der weiteren Annahme, dass es keine DB-Objekte gleichen Attributs-Inhalts gibt, keine Doppelten in der DB)
Zustimmung?

Pack dann nochmal die Entity in das rein HashSet nachdem sie persitiert wurde…

es wird ja wohl vorher und nachher dasselbe eine Objekt sein

Egal wie man es dreht und wendet, die sematische Aenderung der Gleichheit je nachdem ob persitiert wurde oder nicht ist murks und erzeugt weitere Probleme!

hier bist du wieder bei Persistierung statt Änderung der Attribute, das sind doch zwei verschiedene Fragen?

ein equals hinsichtlich Attribute ist bei Änderung der Attribute natürlich so sinnvoll wie ein equals auf Id hinsichtlich Änderung der Id,
warum darüber überhaupt sprechen?

[quote=maki;97626]Du und ich, wir sind unterschiedliche Meschnen, aber nicht weil wir andere Namen haben, ein anderes Geburtsdatum etc. pp.
Sondern schlicht weil du bist, und ich ich bin, wir sind einzigartig als Grundannahme.
Uebertrage dieses Beispiel mal auf Eineiige Zwillinge, selbes Geburtsdatum, selber Nachname, ja sogar exakte Uebereinstimmung bei der DNS!
Wenn die Eltern jetzt dieselben Vornamen fuer beide vergeben, ist es dann nur eine einzige Person?[/quote]

dass man die Attribute überhaupt anschaut wird schon schon seinen Sinn haben,
etwa wenn man ein Objekt in der Verbindungstabelle Elternteil Person Elter, Person Kind anlegt,
da will man vielleicht Doppelte finden,

auch bei dem Zwillingsbeispiel, abgesehen von unrealistischen Fall gleicher Vornamen, kann man noch mit Geburtsuhrzeit oder schlicht Nummerierung 1/2 unterscheiden,
und sich dennoch dafür interessieren dass nicht drei Einträge angelegt werden

[QUOTE=SlaterB][QUOTE=maki;97626]
Du erzeugst eine transiente Entity, packst sie in ein HashSet.
Du aenderst nun einige Werte dieser transienten Entity… und nun?
[/quote]
eben hieß es noch

was denn nun?
[/quote]
Beides!
Wenn dein equals/hashcode auf verggleich von Attributen basieren, aendert sich das Ergebnis schon durch aendern eines Attributes das fuer equals/hashcode herangezogen wird.

[quote=SlaterB;97628]dass diese Methoden bei Änderung der Attribute nicht funktionieren ist ja nun allgemein bekannt,
für den Anlegevorgang von Datenbank-Entities aber nicht gerade üblich (obwohl das natürlich ein weites Feld ist)[/quote]
Das ist absolut ueblich, alles andere waere Quark, vor allem mit relationalen DBs.

Man kann doch nicht nach dem aendern des Nachnahmens einer Person (Heirat, Scheidung und Wiederannahme des Maechennamens, Adoption, Namensaenderung weil nun Kuenstlername…) nicht die alte Person loeschen und eine neue anlegen, die „alte“ Person wird ja schon von zig anderen Tabellen referenziert.

[quote=SlaterB;97628]hinsichtlich dieser einen Frage, Id dazu oder nicht, funktionieren equals/hashcode auf Attributen, evtl. optimiert mit Id-Vergleich,
(spart nur Zeit, ändert nichts, unter der weiteren Annahme, dass es keine DB-Objekten gleichen Attributs-Inhalts gibt, keine Doppelten in der DB)
Zustimmung?[/quote]
Nein, keine Zustimmung!
Abgesehen davon das fachliche Schluessel (Attributwerte) keine gute Sache in RDBMS sind, muss man eben eine bestehende Entity aendern koennen, nciht einfach nur die alte loeschen und eine neue Anlegen.

Falls ich dich richtig verstanden habe natuerlich…

Eben nicht.
Sessions bzw. EntityManager sind ja nicht immer „offen“, deswegen kann man eben auch dieselbe Entity in verschienden Objekten zur Laufzeit in verschiedenen Zustaenden haben (transient, persistiert, geaendert, usw.).

Das ist dieselbe Frage wenn ORM im Spiel sind.
Irgendwie muss ja auch das ORM herausfinden wenn es sich um dieselbe Entity handelt (nutzt du eine IdentityMap: P of EAA: Identity Map).
Objektreferenzen sind da nutzlos, koennte aus einer anderen VM serialisiert werden, oder eben nur aus einer anderen Session, etc. pp.

[quote=SlaterB;97628]ein equals hinsichtlich Attribute ist bei Änderung der Attribute natürlich so sinnvoll wie ein equals auf Id hinsichtlich Änderung der Id,
warum darüber überhaupt sprechen?[/quote]
Eben, die ID darf sich eigentlich niemals aendern, egal wann & wo.
„Gleichheit“ ueber Attribute gehen nur bei ValueObjects, also bei Objekten deren Identitaet sich nur durch die Attrubite definiert, JPA bezeichnet diese als Embeddable, diese muessen immer direkt in Entities abgelegt werden.

[quote=SlaterB;97628]uch bei dem Zwillingsbeispiel, abgesehen von unrealistischen Fall gleicher Vornamen, kann man noch mit Geburtsuhrzeit oder schlicht Nummerierung 1/2 unterscheiden,
und sich dennoch dafür interessieren dass nicht drei Einträge angelegt werden[/quote]
Nummerierung ist auch nur eine Kruecke, der erfolglose Versuch eindeutig zu sein ohne ID :slight_smile:

„für den Anlegevorgang“! für den kurzen Zeitraum vor der Persistierung wo vakant ist ob Id schon da oder noch nicht, das ist das Hauptthema nach wie vor,
deswegen ja zum Teil die Frage, die Id möglichst schnell zu haben, nicht erst nach 10 sec von vielleicht 5 Jahre Lebenszeit der Entity,

‚alte Person löschen‘, das ist doch wieder ganz was anderes, viel später mit längst vorhandener Id, keine Frage mehr ob Id unbekannt,

bei allem lang persitierten, von anderen referenzierten, geht es nur nach Id,
da hat man dann auch kein HashSet mit den Entitäten selber
(wobei wieder weites Feld wer wie bei was auch immer vorgeht, edit: die Doppelten-Prüfung für neue braucht ja ein Set mit den alten :wink: )

Sessions bzw. EntityManager sind ja nicht immer „offen“, deswegen kann man eben auch dieselbe Entity in verschienden Objekten zur Laufzeit in verschiedenen Zustaenden haben (transient, persistiert, geaendert, usw.).

in solchen Fällen hat man immer gewisse Probleme, auch mit equals nach Id

Object A mit Id 45 ist mit Nachname „Müller“ in einem Set,
Object B ist ein separates Objekt, Id 45, ist der neue „Maier“, ehemals „Müller“

wenn man nun B ins Set einfügen will, bleibt A drin,
immerhin kann man mit B remove und dann add ausführen, ob man aber immer an das remove denkt?
erstaunlich das Sets gar kein Overwrite an sich anbieten

besser hat man aber in solchen Fällen eh eine Map Id → Entity, dann ist ein put immer richtig, immer Overwrite, selbst mit einem equals auf Attribute :wink:

[quote=maki;97630]Eben, die ID darf sich eigentlich niemals aendern, egal wann & wo.
„Gleichheit“ ueber Attribute gehen nur bei ValueObjects, also bei Objekten deren Identitaet sich nur durch die Attrubite definiert, JPA bezeichnet diese als Embeddable, diese muessen immer direkt in Entities abgelegt werden.[/quote]
oft genug ist das bei Hibernate-Einträgen mit den Attributen der Fall, etwa bei der Elternteil-Tabelle, bestimmende Attribute Person(Id) Elter + Person(Id) Kind,
deswegen reicht eben oft genug equals nach Attributen nicht nur beim Anlegen und der Frage nach Id vorhanden oder nicht, sondern allgemein durchgehend

und man kann dieses equals dann auch (theoretisch…) nutzen um Doppelte zu finden