-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: NonUniqueObjectException bei Serialisierung vermeiden
PostPosted: Mon Jul 06, 2009 1:23 pm 
Beginner
Beginner

Joined: Thu Oct 04, 2007 12:22 pm
Posts: 48
Hallo!

Ich habe eine einfache Listenstruktur 'ItemList' programmiert, welche eine m-n Beziehung
zu der Klasse 'Item' besitzt. Ein Beispiel, wie sie erzeugt und persistiert wird:

Code:
ItemList myList = new ItemList();
myList.add(new Item(id1));
myList.add(new Item(id2));
...

// Transaktion starten
session.saveOrUpdate(myList);
// Transaktion schließen


Das funktioniert wunderbar. Allerdings erhalte eine Listeninstanz auch serialisiert über das
Netzwerk (AMF-Protokoll). Wenn die Liste nun aber zweimal das Gleiche Item zugewiesen
bekommt (was ausdrücklich funktionieren soll/ PK ist eine long-ID des Items), dann deserialisieren
sich die zwei Items zu unterschiedlichen Referenzen mit der gleichen ID. Beim Speichern der
Liste schmeißt Hibernate somit eine NonUniqueObjectException, da zweimal der gleiche PK
aus unterschiedlichen Objektreferenzen mit der Session verbunden wird.
Ich habe dann versucht, das Caching abzuschalten via
Code:
getSession().setCacheMode(CacheMode.IGNORE);

in der Hoffnung, die Kollision würde so nicht geprüft werden. Leider ohne Erfolg.

Weiß jemand eine Lösung?


Top
 Profile  
 
 Post subject: Re: NonUniqueObjectException bei Serialisierung vermeiden
PostPosted: Tue Jul 07, 2009 12:00 pm 
Regular
Regular

Joined: Thu Apr 14, 2005 10:39 am
Posts: 115
Hallo,
also die Unique-Prüfung hat mit dem Cache nichts zu tun. Spätestens wenn das zweite Objekt mit der gleichen ID geschrieben würde, würde es schief gehen.

Es kann keine zwei Objekte mit der gleichen (künstlich oder natürlich ist egal) ID in der selben Datenbank geben.

Zur Laufzeit in der VM schon. D. h. Du musst dafür Sorge trage, dass nur ein Objekt existiert oder die ID auf eine noch nicht vergebene ändern. (Falls Du Kopien explizit erstellen willst.)

Mein Vorschlag wäre Du benutzt ein Set und überschreibst equals und hashcode entsprechend, dann eliminiert Set die Duplikate von selbst.

Viele Grüße Michael


Top
 Profile  
 
 Post subject: Re: NonUniqueObjectException bei Serialisierung vermeiden
PostPosted: Wed Sep 16, 2009 12:24 pm 
Beginner
Beginner

Joined: Thu Oct 04, 2007 12:22 pm
Posts: 48
Erstmal danke für Deine Antwort, leider habe ich lange keine Möglichkeit gehabt, mich noch einmal um das Problem
zu kümmern. Allerdings ist die Lösung mit einem Set für meinen Fall nicht geeignet. Vielleicht sollte ich meinen
Anwendungsfall nochmal genauer erklären.

Es gibt ein Item mit den Attributen:

Code:
id, name


Nun soll es möglich sein, Listen von diesen Items anzulegen, ähnlich bookmarks. Das Wichtige (und gleichzeitig das
Problem) ist, dass es auch möglich sein soll, Listen anzulegen, die mehrfach das gleiche Element beinhalten. Also ein
Beispiel anhand der IDs: 1, 2, 3, 1.

Also habe ich eine Klasse ItemList erstellt, welche besteht aus:
Code:
id, List<Item>, name


Durch das Hibernatemapping als m-n Beziehung entsteht eine cross-Tabelle, die das mapping übernimmt über:
Code:
listId (PK), itemId (PK), position


Rein datenbanktechnisch also kein Problem, ein m-n mapping vorzunehmen.
In meinen (vorerst fehlerhaften) unit tests ist das Problem auch nicht aufgetaucht, weil der 1st Level Cache hier
gleiche Referenzen erkennt:

Code:
Item1 item1 = new Item(...);
// zwei identische Einträge in einer Liste
myList.add(item1);
myList.add(item1);
session.saveOrUpdate(myList);

Dies legt mir tatsächlich eine Liste mit zwei identischen Einträgen an.

Der Test entspricht aber nicht meiner Situation, in der ich die Liste über RPC und somit deserialisiert bekomme.
In dem Fall hätten die beiden Einträge nicht die gleiche Referenz, sie wären nur inhaltsgleich. Dadurch geht der
1st Level-Cache von kollidieren Einträgen aus (wie Du ja bereits gesagt hast).

Mein Fehler ist also, dass ich eine Liste benutze, bei der Hibernate versucht, auch die Items selbst zu speichern,
obwohl mich nur die Einträge in der Crosstabelle (die eigentliche Liste) interessiert. Allerdings möchte ich auch einen
Listentype benutzen, bei dem automatisch die Item-Entities referenziert und mitgeladen werden, wenn ich die Liste
lade.


Top
 Profile  
 
 Post subject: Re: NonUniqueObjectException bei Serialisierung vermeiden
PostPosted: Thu Sep 17, 2009 3:55 am 
Regular
Regular

Joined: Thu Apr 14, 2005 10:39 am
Posts: 115
Hallo,

würde am ehesten sicherstellen, das Du von RPC gelieferte doppelte Instanzen eliminierst.
Musst Dir natürlich sicher sein, dass sie in der Zwischenzeit nicht geändert wurden. (Evtl. über Versionsattribut @Version)

Würde in einer Liste alle bereits geladenen Instanzen (Referenzen) speichern und falls die gleiche Instanz erneut geladen wird, diese mit der bereits geladenen ersetzen. Somit dürftest Du nur an einer Stelle eingreifen müssen und der Rest sollte dann funktionieren. Bei großen Datenmenge bekommst Du evtl. mit dem Garbage-Collector Probleme, so dass Du evtl. WeakReference benutzen solltest für die obige Liste.

VG Michael


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.