代码之家  ›  专栏  ›  技术社区  ›  Satya

使用xstream序列化hibernate对象的问题

  •  5
  • Satya  · 技术社区  · 16 年前

    我一直面临这样一个问题:序列化时的hibernate对象会生成包含hibernate中所有检测代码的意外xml。

    在序列化对象之前,我们对该对象进行了一些清理。

    但是,是否有一个标准选项可以直接序列化对象?

    6 回复  |  直到 16 年前
        1
  •  3
  •   cliff.meyers    13 年前

    我以前没有使用过xstream,但是我已经序列化了hibernate托管的实体。这不好玩。

    有两大问题:

    • 延迟加载;
    • 一对多的关系。

    前者是显而易见的-您需要实际的数据来序列化。后者则不那么重要-针对集合接口声明的任何一对多关系(例如: Set<T> )会被hibernate自己的(不可更改!)集合实现。这很可能是hibernate的类向对象中渗透的地方。

    我最后写了反射代码(实际上是内省的)实现了这一点:

    1. 在会话打开时,触摸整个对象图以强制加载任何已卸载的实体;
    2. 关闭了hibernate会话(包括涉及其连接的任何事务);
    3. 遍历对象图,用ArrayList、HashSet或HashMap(已知的可序列化集合)的实例替换任何列表、集合或映射。

    注意,步骤2很重要-如果在关闭会话之前替换了集合,hibernate只会在关闭时重新放置自己的集合…

    编辑: @cliff.meyers发现了一个我忘了提到的实现细节:如果这样做,您需要限制对象图只对自己的实体进行遍历,并注意循环引用路径(例如:通过缓存对已遍历对象的引用)。

        2
  •  3
  •   Tomek Lipski    13 年前

    我已经想出了一些足够的解决办法。在我的应用程序中,只有persistentsets扰乱了xstream生成的xml。因此,我向xstream添加了另一个转换器(它与open hibernate会话和live对象一起运行):

    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>
    

    在我的例子中,类属性并不重要,所以我忽略了它的值。你当然可以修补它。

        3
  •  3
  •   Mort    12 年前

    xstream现在提供了一个单独的模块/jar来处理hibernate集合。请看 XStream's FAQ for an example.

        4
  •  1
  •   cliff.meyers    16 年前

    在codehaus jira上有一些关于这个(和示例代码)的信息:

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

    我们为其他一些远程处理实现(Axis1、BlazeDS等)编写了一些工具来解决这类问题。我们所做的与dan的解决方案非常相似,尽管我们添加了声明要行走的对象路径和要“截取”的对象路径的功能,因为在许多情况下,我们对所有数据都不感兴趣;这也会导致“n+1选择”问题的严重问题,该问题发生在成千上万的tiMES!:)我认为实现xstream转换器将是最佳方法,因为您只需遍历对象图一次。如果您在会话中设置flushmode.manual,那么您还应该能够在运行时修改对象图,而不必让hibernate做任何讨厌的事情。尽管这是一种比较先进的技术,但要小心使用。

        5
  •  1
  •   anzaan    14 年前

    虽然我没有使用hibernate,但我也遇到了类似的问题。我看了一下enitity修枝机,但它不完全是我要找的,因为我正在寻找一个更简单的解决方案。

    我提出了一个非常简单的解决方案,它使用反射来去除cglib增强的对象,就像一个符咒。

    请访问 http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/ 例如和代码。

        6
  •  1
  •   Ophir Radnitz    12 年前

    没用过,但是 xstream-for-beans 似乎合适(引用):

    该项目提供了映射器和转换器的实现,这些映射器和转换器在以下方面增强了xstream:

    1. 序列化由getter和setter公开的对象。字段可用的xstream特性应适用于为getter/setter属性定义的属性。
    2. 清理托管对象的序列化:自动忽略不相关的字段和类 信息。
    3. 处理“脱机”字段和代理对象。

    我写过一次自定义xstream Converter 不幸的是,作为封闭源代码项目的一部分,我们要处理这个问题。xstream for beans处理同样的问题,值得一试。

    我用过兵马俑 Pojoizer 实用性在过去是成功的,但我认为它已经不再被维护了。