Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[JAVA] Hibernate Object.equals() override problematiek

Pagina: 1
Acties:

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 14:09
Ik loop bij het overriden van de Object.equals() methode in combinatie met Hibernate tegen een catch-22 situatie aan, waar ik even geen elegante oplossing voor zie. De code in kwestie is niet heel erg relevant, maar waar het op neer komt:

- In de equals() methode ben ik gewend om type-checking uit te voeren door het vergelijken van de resultaten die Object.getClass() retourneren, i.p.v. de instanceof operator te gebruiken, zodat er altijd aan de symmetrie eis uit het equals() contract voldaan wordt.

- Wanneer ik een object, die over een dergelijke implementatie van equals() beschikt, gebruik in een HashMap die ik met Hibernate persisteer, dan retourneert de equals() methode altijd false. Hibernate vult, bij het ophalen van een Map implementatie, die Map met Proxy objecten. Wanneer ik dan een get() aanroep op die Map worden de key objecten van type MyObjectProxy, via de euqlas() methode, vergeleken met een MyObject instantie die als parameter wordt meegegeven. Die zijn volgens bovenstaande definitie (getClass() vergelijking) dus niet gelijk.

- Wanneer ik dit oplos door toch de instanceof operator te gebruiken, zou ik de klasse in kwestie het liefst final willen declareren, zodat er geen subklassen gemaakt kunnen worden, die de symmetrie eis van equals() kunnen verstoren. Echter, dan kan ik de klasse weer niet als key in een lazy Hibernate collection gebruiken, omdat Hibernate er een subklasse van moet kunnnen maken: het Proxy object.

Ik loop dus altijd tegen een muur aan, ongeacht welk alternatief ik kies. Zie ik de oplossing over het hoofd of moet ik concessies doen?

  • Salandur
  • Registratie: Mei 2003
  • Laatst online: 29-11 18:34

Salandur

Software Engineer

waarom wil je voorkomen dat er een subclass gecreeerd wordt? dan kan hibernate niet meer lazy loaden en heb je er niet zoveel aan.

met een goede editor kan je equals() en hashCode() genereren op basis van velden. deze zal bijna altijd gebruik maken van instanceof, om jou probleem te voorkomen

Assumptions are the mother of all fuck ups | iRacing Profiel


  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 14:09
Salandur schreef op donderdag 25 oktober 2007 @ 13:12:
waarom wil je voorkomen dat er een subclass gecreeerd wordt? dan kan hibernate niet meer lazy loaden en heb je er niet zoveel aan.

met een goede editor kan je equals() en hashCode() genereren op basis van velden. deze zal bijna altijd gebruik maken van instanceof, om jou probleem te voorkomen
Ik ben me er van bewust dat Hibernate geen Proxy object kan maken, wanneer ik de klasse final declareer, dus dat kan sowieso niet. Dat zou ook niet nodig zijn, als ik in de equals() methode type-checking zou kunnen toepassen door de getClass() resultaten te vergelijken, maar dat kan ook niet, omdat Hibernate dan vind dat zijn Proxy objecten niet conceptueel gelijk zijn aan de originelen.
De enige oplossing, waarmee type-checking wel geïmplementeerd kan worden, die ook werkt i.c.m. Hibernate is de instanceof operator. Het gebruik daarvan is een risico, omdat de symetrie eis in het contract van Object.equals dan niet gegarandeerd kan worden, tenzij je de klasse final declareert, zodat er geen subklassen gemaakt kunnen worden. Echter, dan kan Hibernate weer geen Proxy objecten maken....

En zo is het cirkeltje rond.

De 'oplossingen' die ik zie, zijn:
- Het risico voor lief nemen en toch de instanceof operator gebruiken.
- Geen lazy loading gebruiken.

[ Voor 5% gewijzigd door Kwistnix op 25-10-2007 13:43 ]


  • Salandur
  • Registratie: Mei 2003
  • Laatst online: 29-11 18:34

Salandur

Software Engineer

even gekeken wat eclipse standaard genereerd:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    final Object other = (Object ) obj;
    if (field1== null) {
      if (other.field1!= null) return false;
    }
    else if (!field1.equals(other.field1)) return false;
    if (field2== null) {
      if (other.field2!= null) return false;
    }
    else if (!field2.equals(other.field2)) return false;
    if (field3== null) {
      if (other.field3!= null) return false;
    }
    else if (!field3.equals(other.field3)) return false;

    return true;
  }


hierin wordt inderdaad geen gebruik gemaakt van de instanceof operatie. ik ben zelf overigens nog nooit tegen gekomen dat hibernate hier een probleem mee heeft, en we laden vaak genoeg een collectie

[ Voor 10% gewijzigd door Salandur op 25-10-2007 13:28 . Reden: variabelen hernoemt ]

Assumptions are the mother of all fuck ups | iRacing Profiel