【问题标题】:How to "slice" a POJO如何“切片” POJO
【发布时间】:2010-07-22 00:04:12
【问题描述】:

我从 C++ 中借用了“切片”的含义。

假设我有一个通过 Hibernate 持久化的简单 POJO:

class Person {
private long id;
private String name;
...
// getters and setters here
...
}

现在,当我从数据库中检索一个对象时,我知道它是由 Hibernate “检测”的(它的真实类是自动生成的 Person 派生类)。我想将它转换回一个“普通”的人对象。例如,将使用 Tnat 将对象提交给 XStream 并让结果仅包含 Person 包含的内容。

我可以通过定义一个复制构造函数来做到这一点,但是我不想为每个 ORM 类编写复制构造函数的麻烦(更不用说违反 DRY 原则了)。

所以我想知道如果

a) 是否已经有一个 Java 库可以做到这一点? b) 如果没有,用反射写一个是否可行?

在 (b) 的情况下,任何建议/指南/代码框架都将不胜感激。

【问题讨论】:

    标签: java reflection pojo slice


    【解决方案1】:

    bean 映射库Dozer 在这方面做得非常出色,而且使用起来非常简单。

    只需将 Hibernate 返回的 bean 实例映射到它自己的类:

    Person person = session.load(...);
    BeanMapper mapper = ...;
    Person cleanPerson = mapper.map(person, Person.class);
    

    瞧,不再有 Hibernate 代理或延迟加载的集合!

    【讨论】:

    • 这是一个完美的解决方案。它甚至解决了我没有提到的另一个问题,即一对多关系需要在持久对象中表示为容器,在 XML-ed 对象中表示为数组。非常感谢。
    • Dozer 的真正目的是从 TypeA 映射到 TypeB,并且能够将该映射存储在 XML 配置而不是 Java 代码中,因此它也非常适合该用途(真正从一个键入另一个)。
    【解决方案2】:

    org.apache.commons.beanutils.BeanUtilsBean 类几乎可以满足您的所有需求。 copyProperties 方法将通过调用您的实体上的 getter 并在您提供的目标对象上查找具有匹配属性名称的 setter。您可能需要处理一些嵌套实体,具体取决于您想要什么样的行为以及是否/如何映射关系。

    如果您需要变得更复杂,您可以注册一个转换器来将您的嵌套实体类型转换为其他类型。

    【讨论】:

    • 谢谢。它部分地解决了这个问题。但我更多地考虑像 mybject=Slicer.slice(myObject, Person.class) 这样的方法。它将创建一个新的 Person 对象(在第二个参数上调用 newInstance)并遍历它以了解要复制的内容。这样,我将完全避免编写特定于案例的代码。
    【解决方案3】:

    这里有一个关于你的问题的有趣讨论

    http://www.mojavelinux.com/blog/archives/2006/06/hibernate_get_out_of_my_pojo/

    在 cmets 中提出了几种解决方案。特别是

    http://code.google.com/p/entity-pruner/

    http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/

    我个人非常重视层分离,并认为您想要通过网络或 XML 序列化的类实际上应该与您的数据访问层类分开,这也可以解决问题。

    class SerializablePerson
    {
       ... fields you care about ...
       SerializablePerson(Person person)
       {
          ... set only what you care about ... 
       }
    
    }
    

    【讨论】:

      【解决方案4】:

      你可以有一个没有持久性信息的 Person 类,由持久性对应物包装,如下所示:

      public class Person implements Serializable
      {
         private String name;
         // others.
      }
      
      public class PersistentPerson
      {
         private Long id;
         private Person data; //
      
         public Person getPerson() { return this.data; } 
      }
      

      我不确定这个设计是否值得。就在写这个例子的时候,双重模型让我有点呕吐。

      更大的问题是:您为什么认为这是必要的?如果没有好的方法告诉 XStream 在序列化时不包含 id,我会说最好编写自己的 javax.xml.bind.Marshallerjavax.xml.bind.Unmarshaller 以获得你想要的。

      有更好的方法来解决这个问题,而不是把你的整个设计混为一谈。

      【讨论】:

      • 谢谢,但这会比只做一个复制构造函数或像 Pete 建议的那样使两个对象独立。
      • Person 完全独立于 PersistentPerson。你必须至少有一个单向的关系。就个人而言,我认为层分离几乎没有那么重要。
      猜你喜欢
      • 2021-04-06
      • 2020-02-16
      • 1970-01-01
      • 2012-08-09
      • 2011-06-20
      • 1970-01-01
      • 2018-08-16
      • 2019-07-23
      • 2019-11-29
      相关资源
      最近更新 更多