2008-11-30 6 views
5

Ich habe dieses Problem, bei dem die Hibernate-Objekte bei der Serialisierung unerwartete xmls erzeugt, die den gesamten instrumentierten Code aus Hibernate enthalten.Problem beim Serialisieren von Hibernate-Objekten mit XStream

Wir haben eine Reinigung des Objekts vor der Serialisierung des Objekts durchgeführt.

Aber gibt es eine Standardoption, um das Objekt direkt zu serialisieren?

+0

Vielleicht könnten Sie zeigen, wie das XML aussieht? –

Antwort

3

Ich habe XStream noch nicht verwendet, aber ich habe Hibernate-verwalteten Entitäten serialisiert. Es macht keinen Spaß.

Es gibt zwei große Probleme:

  • Lazy Loading;
  • Eins-zu-viele-Beziehungen.

Die erste ist offensichtlich - Sie brauchen die eigentlichen Daten zu serialisieren. Letzteres ist weniger der Fall - alle Eins-zu-Viele-Beziehungen, die Sie gegen Sammelschnittstellen deklarieren (zB: Set<T>), werden von Hibernate's eigenen (unserialisierbaren!) Sammlungsimplementierungen verstopft. Dies kann gut sein, wo Hibernate's Klassen in Ihre Objekte bluten.

ich reflektierenden Code endete schriftlich (tatsächlich introspektiv), die dies taten:

  1. Mit der Sitzung geöffnet, berühren das gesamte Objekt Diagramm, um zwang zu laden alle entladen Einheiten;
  2. Die Hibernate-Sitzung geschlossen (einschließlich aller Transaktionen, die die Verbindung betreffen);
  3. Ging das Objektdiagramm, ersetzt alle Listen, Sets oder Maps mit Instanzen von ArrayList, HashSet oder HashMap (bekannt-serialisierbaren Sammlungen).

Beachten Sie, dass 2 Schritt ist wichtig - wenn Sie die Sammlungen Schließen der Sitzung vor ersetzen, Hibernate nur seine eigenen Sammlungen gleich wieder auf schließen ...

Edit: @ cliff.meyers entdeckte ein Detail der Implementierung, die ich vergessen habe zu erwähnen: Wenn Sie dies tun, müssen Sie das Objektgraph-Gehen nur auf Ihre eigenen Entitäten beschränken und nach zirkulären Referenzpfaden suchen (z. B. indem Referenzen auf Objekte, die Sie bereits betreten haben, zwischengespeichert werden).

1

Es gibt einige Informationen über diesen (und Beispielcode) über an dem Codehaus JIRA:

http://jira.codehaus.org/browse/XSTR-226

Wir schrieben einige Werkzeuge für eine Reihe von anderen Remoting-Implementierungen um diese Art von Problem zu arbeiten (Axis 1, Blaze DS, usw.). Was wir getan haben, ist der Lösung von Dan sehr ähnlich, obwohl wir die Fähigkeit hinzugefügt haben, zu deklarieren, welche Objektpfade gehen und welche "abschneiden", weil wir in vielen Situationen nicht an allen Daten interessiert waren; es hätte auch zu ernsthaften Problemen mit dem "n + 1 selects" Problem geführt, das tausende Male passiert ist! :) Ich denke, die Implementierung eines XStream-Konverters wäre der optimale Ansatz, da Sie das Objektdiagramm nur einmal durchlaufen müssen. Wenn Sie FlushMode.MANUAL in Ihrer Sitzung festlegen, sollten Sie auch in der Lage sein, die Objektgrafik zu ändern, ohne dass Hibernate etwas Unangenehmes tut. Verwenden Sie dies jedoch mit Vorsicht, da es sich um eine etwas fortgeschrittene Technik handelt.

+0

Hoppla, habe vergessen, anfänglich limitierende Objekttypen zu erwähnen, in die man runtersteigt (deine Snip-Syntax) - danke für die Korrektur ... –

3

Ich habe eine etwas ausreichende Lösung gefunden. In meiner Anwendung verfälschten nur PersistentSets XML, das von XStream generiert wurde. So habe ich einen anderen Konverter XStream (die mit offenen Hibernate Session läuft und Live-Objekte) hinzugefügt:

XStream xs = new XStream(); 
xs.registerConverter(new CollectionConverter(xs.getMapper()) { 
    @Override 
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { 
     org.hibernate.collection.PersistentSet ps = (PersistentSet) source; 
     super.marshal(new HashSet(ps), writer, context); 
    } 

    @Override 
    public boolean canConvert(Class type) { 
     return type.isAssignableFrom(org.hibernate.collection.PersistentSet.class); 
    } 
}, XStream.PRIORITY_VERY_HIGH); 
String s = xs.toXML(processInstance); 

Die serialisierte XML wie unten aussieht:

<processLogs class="org.hibernate.collection.PersistentSet"> 
    <pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 
     <id>813017</id> 
     <entryDate> 
     <time>1310832421216</time> 
     <timezone>GMT</timezone> 
     </entryDate> 
     <eventI18NKey>process.log.action-performed</eventI18NKey> 
     <additionalInfo>Wydrukuj wniosek</additionalInfo> 
     <logValue>GENERATE_APPLICATION</logValue> 
     <logType>PERFORM_ACTION</logType> 
     <state reference="../../../definition/states/pl.net.bluesoft.rnd.processtool.model.config.ProcessStateConfiguration[8]"/> 
     <processInstance reference="../../.."/> 
     <user reference="../../../creator"/> 
    </pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 
    <pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 
     <id>808211</id> 
     <entryDate> 
     <time>1310828206169</time> 
     <timezone>GMT</timezone> 
     </entryDate> 
     <eventI18NKey>process.log.action-performed</eventI18NKey> 
     <additionalInfo>Zaakceptuj</additionalInfo> 
     <logValue>ACCEPT</logValue> 
     <logType>PERFORM_ACTION</logType> 
     <state reference="../../../definition/states/pl.net.bluesoft.rnd.processtool.model.config.ProcessStateConfiguration[4]"/> 
     <processInstance reference="../../.."/> 
     <user reference="../../../creator"/> 
    </pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog> 

In meinem Fall die Klasse Attribut nicht wichtig, also habe ich seinen Wert ignoriert. Sie können natürlich damit basteln.

+0

+1 Sehr nützlich, danke! Mein nächstes Problem ist ein PersistentSet, das in ein UnmodiableSet eingepackt ist, was ärgerlicherweise keine sichtbare Klasse ist: -/ – Rup

+0

Um das Klassenattribut zu unterdrücken, müssen Sie einen benutzerdefinierten Mapper implementieren, der serializedClass (PersistentSet.class) == HashSet zurückgibt .Klasse. Aber es sieht so aus, als ob es eine Menge Arbeit ist. – Rup

1

nicht benutzt haben, aber xstream-for-beans scheint (Zitat) zu passen:

Dieses Projekt Implementierung von Mapper und Wandler liefert, die XStream verbessern auf folgende Aspekte:

  1. Serialize Objekte, wie sie werden von Getter und Setter ausgesetzt. XStream-Funktionen, die für Felder verfügbar sind, müssen für Eigenschaften funktionieren, die für Getter/Setter-Eigenschaften definiert sind.
  2. Serialisierung verwalteter Objekte bereinigen: irrelevante Felder und Klasse Informationen automatisch auslassen.
  3. Handle "offline" Felder und Proxy-Objekte.

Ich schrieb einmal benutzerdefinierten XStream Converter s mit diesem Thema, als Teil eines Closed-Source-Projekt leider beschäftigen. Xstream-for-Beans beschäftigt sich mit den gleichen Problemen, einen Versuch wert.

Ich habe Terracottas Pojoizer Dienstprogramm erfolgreich in der Vergangenheit verwendet, aber ich denke nicht, dass es nicht mehr gepflegt wird.

Verwandte Themen