如何“切片”一个POJO
我借用了 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)的情况下,任何建议/指南/代码框架将不胜感激。
I'm borrowing the "slice" meaning from C++.
Let's say I hava a simple POJO that's persisted via Hibernate:
class Person {
private long id;
private String name;
...
// getters and setters here
...
}
Now, when I retrieve an object from the database I know it was "instrumented" by Hibernate (its real class is a Person-derived generated automatically). I want to convert it back to a "plain" person object. Tnat would be used, for instance, to submit the object to XStream and have the result containing only what Person contains.
I could do it by defining a copy constructor, but I don't want to have the hassle of having to write copy constructors for every ORM class (not to mention the violation of DRY principle).
So I was wondering if
a) is there already a Java lib that does it?
b) If not, would it be practical to write one using reflection?
In case of (b), any recomendations/guidelines/code skeletons would be appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以拥有一个没有由持久性对应项包装的持久性信息的 Person 类,如下所示:
我不确定该设计是否值得。就在写这个例子的时候,双重模型让我有点呕吐。
更大的问题是:为什么你认为这是必要的?如果没有好的方法告诉 XStream 在序列化时不包含
id
,我会说最好编写自己的javax.xml.bind.Marshaller
和 javax.xml.bind.Unmarshaller 来得到你想要的。有比破坏整个设计更好的方法来解决这个问题。
You could have a Person class without persistence information wrapped by a persistent counterpart, like this:
I'm not sure the design is worth it. The dual model makes me throw up in my mouth a little, just while writing this example.
The larger question is: Why do you think this is necessary? IF there's no good way to tell XStream to not include the
id
when serializing, I'd say it'd be better to write your ownjavax.xml.bind.Marshaller
andjavax.xml.bind.Unmarshaller
to get what you want.There are better ways to solve this problem than bastardizing your entire design.
这里有一个关于您的问题的有趣讨论
http://www.mojavelinux。 com/blog/archives/2006/06/hibernate_get_out_of_my_pojo/
评论中提出了几种解决方案。特别是
http://code.google.com/p/entity-pruner/
http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/" anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/
我个人非常喜欢层分离,并且认为您想要通过网络序列化的类或XML 实际上应该与数据访问层类分开,这也可以解决问题。
There is an interesting discussion about your problem here
http://www.mojavelinux.com/blog/archives/2006/06/hibernate_get_out_of_my_pojo/
Several solutions are proposed in the comments. In particular
http://code.google.com/p/entity-pruner/
http://www.anzaan.com/2010/06/serializing-cglib-enhanced-proxy-into-json-using-xstream/
I personally am huge on layer separation, and would argue that classes that you want to serialize across the wire or to XML should actually be separate from your data access layer classes, which would also solve the problem.
org.apache.commons.beanutils.BeanUtilsBean 类可能几乎可以完成您想要的所有操作。 copyProperties 方法将调用实体上的 getter,并在您提供的目标对象上查找具有匹配属性名称的 setter。您可能需要处理一些嵌套实体,具体取决于您想要什么样的行为以及是否/如何映射关系。
如果您需要变得更复杂,您可以注册一个转换器来将嵌套实体类型转换为其他类型。
The class
org.apache.commons.beanutils.BeanUtilsBean
probably does almost everything you want. The copyProperties method will go through calling the getters on your Entity and looking for setters with a matching property name on a target object you provide. You may need to handle some nested entities, depending on what kind of behavior you want and if/how you map relationships.If you need to get more sophisticated you can register a Converter for turning your nested entity types into something else as well.
bean 映射库 Dozer 在这方面做得非常出色,而且使用起来非常简单。
只需将 Hibernate 返回的 bean 实例映射到它自己的类:
瞧,不再需要 Hibernate 代理或延迟加载集合!
The bean mapping library Dozer does an excellent job of this and is dead simple to use.
Simply map an instance of the bean returned by Hibernate to it's own class:
voila, no more Hibernate proxies or lazy-loaded collections!