我一直在面对这个问题,序列化上的hibernate对象产生了包含来自Hibernate的所有检测代码的意外xmls。
在序列化对象之前,我们对对象进行了一些清理。
但是,是否有可用于直接序列化对象的标准选项?
答案 0 :(得分:3)
之前我没有使用过XStream,但是我已经序列化了Hibernate管理的实体。这不好玩。
有两个大问题:
前者显而易见 - 您需要实际数据来序列化。后者不那么 - 你对集合接口声明的任何一对多关系(例如:Set<T>
)将被Hibernate自己的(不可序列化的!)集合实现插入。这很可能是Hibernate的类正在流入你的对象的地方。
我最终编写了这样做的反射代码(实际上是内省的):
请注意,第2步非常重要 - 如果您在关闭会话之前更换集合,Hibernate只会在关闭时将其自己的集合放回原位...
编辑: @ cliff.meyers发现了我忘记提及的实现细节:如果你这样做,你需要限制对象图只走到你自己的实体,并观察循环引用路径(例如:通过缓存对已经走过的对象的引用)。
答案 1 :(得分:3)
我想出了一些足够的解决方案。在我的应用程序中,只有PersistentSets搞乱了XStream生成的XML。所以我添加了另一个转换器到XStream(它使用打开的Hibernate Session和活动对象运行):
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);
序列化的XML如下所示:
<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>
就我而言,class属性并不重要,所以我忽略了它的值。你当然可以修补它。
答案 2 :(得分:3)
XStream现在提供了一个单独的模块/ jar来处理Hibernate集合。请参阅XStream's FAQ for an example.
答案 3 :(得分:1)
在Codehaus JIRA上有一些关于此(和示例代码)的信息:
http://jira.codehaus.org/browse/XSTR-226
我们为一些其他远程实现(Axis 1,Blaze DS等)编写了一些解决此类问题的工具。我们所做的与Dan的解决方案非常相似,尽管我们添加了声明哪些对象路径可以走路以及哪些“剪切”的能力,因为在许多情况下我们对所有数据都不感兴趣;它也会导致严重的问题,“n + 1选择”问题发生了数千次! :)我认为实现XStream转换器将是最佳方法,因为您只需要遍历对象图一次。如果你在Session上设置了FlushMode.MANUAL,那么你也应该能够在没有Hibernate做任何讨厌的情况下修改对象图。请谨慎使用,因为这是一种先进的技术。
答案 4 :(得分:1)
虽然我没有使用hibernate,但我遇到了类似的问题。我看着enitity-pruner,但它不是我想要的,因为我正在寻找一个更简单的解决方案。
我想出了一个非常简单的解决方案,它使用反射来消除CGLIB的阴影对象,如魅力。
请访问http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/例如代码。
答案 5 :(得分:1)
没有使用它,但xstream-for-beans似乎适合(引用):
该项目提供了在以下方面增强XStream的映射器和转换器的实现:
- 序列化由getter和setter公开的对象。可用于字段的XStream功能应适用于为getter / setter proprerties定义的属性。
- 清理托管对象的序列化:自动省略不相关的字段和类 信息。
- 处理“离线”字段和代理对象。
醇>
我写了一次自定义XStream Converter
来处理这个问题,不幸的是,它是一个闭源项目的一部分。 xstream-for-beans处理同样的问题,非常值得一试。
我过去曾成功使用过Terracotta的Pojoizer实用程序,但我不认为它已经被维护了。