Issue with serializing Hibernate objects using XStream

前端 未结 6 1514
南笙
南笙 2021-02-04 19:52

I\'ve been facing this issue where, the hibernate objects on serialization produces unexpect xmls containing all the instrumented code from Hibernate.

We did some cleani

相关标签:
6条回答
  • 2021-02-04 20:21

    There is some info on this (and sample code) over at the Codehaus JIRA:

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

    We wrote some tools to work around this sort of issue for a bunch of other remoting implementations (Axis 1, Blaze DS, etc). What we did is very similar to Dan's solution, although we added the ability to declare which object paths to walk and which to "snip" because in many situations we were not interested in all the data; it also would have led to serious issues with the "n+1 selects" problem happening thousands of times! :) I think implementing an XStream converter would be the optimal approach since you'd only have to walk the object graph once. If you set FlushMode.MANUAL on your Session you should also be able to modify the object graph as you go without Hibernate doing anything nasty. Use this with caution though as it's a somewhat advanced technique.

    0 讨论(0)
  • 2021-02-04 20:27

    I've came up with somewhat sufficient solution. In my application, only PersistentSets were messing up XML generated by XStream. So I have added another Converter to XStream (which runs with open Hibernate Session and live objects):

    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);
    

    The serialized XML looks like below:

      <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 my case, the class attribute was not important, so I have ignored its value. You can of course tinker with it.

    0 讨论(0)
  • 2021-02-04 20:27

    XStream now provides a separate module/jar to handle Hibernate collections. Please see XStream's FAQ for an example.

    0 讨论(0)
  • 2021-02-04 20:29

    I faced a similar problem although Im not using hibernate. I looked at the enitity-pruner but its not quite what i was looking for as I was looking for a more simpler solution.

    I came up with a very simple solution using reflection that deproxies CGLIB enhaned objects like a charm.

    please visit http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/ for example and code.

    0 讨论(0)
  • 2021-02-04 20:33

    I've not used XStream before, but I have serialized Hibernate-managed entities. It isn't fun.

    There are two big issues:

    • Lazy loading;
    • One-to-many relationships.

    The former is obvious - you need the actual data to serialize. The latter is less so - any one-to-many relationships you declare against collection interfaces (eg: Set<T>) will get plugged by Hibernate's own (unserializable!) collection implementations. This may well be where Hibernate's classes are bleeding into your objects.

    I ended up writing reflective code (actually introspective) that did this:

    1. With the session open, touched the entire object graph to force-load any unloaded entities;
    2. Closed the Hibernate session (including any transactions involving its connection);
    3. Walked the object graph, replacing any lists, sets or maps with instances of ArrayList, HashSet or HashMap (known-serializable collections).

    Note that step 2 is important - if you replace the collections prior to closing the session, Hibernate will just put its own collections right back upon close...

    Edit: @cliff.meyers spotted a detail of the implementation I forgot to mention: if you do this, you need to limit object graph walking only to your own entities, and watch for circular reference paths (eg: by caching references to objects you've already walked).

    0 讨论(0)
  • 2021-02-04 20:33

    Haven't used it, but xstream-for-beans seems to fit (quoting):

    This project provides implementation of mappers and converters that enhance XStream on following aspects:

    1. Serialize objects as they are exposed by getters and setters. XStream features available for fields shall work for properties defined for getter/setter proprerties.
    2. Sanitize serialization of managed objects: automatically omit irrelevant fields and class information.
    3. Handle "offline" fields and proxy objects.

    I wrote once custom XStream Converters to deal with this issue, as a part of a closed-source project unfortunately. xstream-for-beans deals with the very same problems, well worth a shot.

    I've used Terracotta's Pojoizer utility successfully in the past, but I don't think it's maintained anymore.

    0 讨论(0)
提交回复
热议问题