views:

73

answers:

4

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.

+1  A: 

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.

Affe
Thanks. It solves the problem partially. But I was thinking more about a method like mybject=Slicer.slice(myObject, Person.class). It would create a new Person object (calling newInstance on the second parameter) and traverse it to know what to copy. This way, I would avoid entirely the need to write case-specific code.
Fabio Ceconello
A: 

You could have a Person class without persistence information wrapped by a persistent counterpart, like this:

public class Person implements Serializable
{
   private String name;
   // others.
}

public class PersistentPerson
{
   private Long id;
   private Person data; //

   public Person getPerson() { return this.data; } 
}

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 own javax.xml.bind.Marshaller and javax.xml.bind.Unmarshaller to get what you want.

There are better ways to solve this problem than bastardizing your entire design.

duffymo
Thanks, but this would be more work (and also make the code less readable) than doing just a copy constructor or making the two objects independent as Pete suggested.
Fabio Ceconello
Person is completely independent of PersistentPerson. You have to have at least a one-way relationship. Personally, I think that layer separation isn't nearly that important.
duffymo
+1  A: 

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.

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

}
Pete
+3  A: 

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:

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

voila, no more Hibernate proxies or lazy-loaded collections!

matt b
That's a perfect solution. It even solves another problem I didn't mention, the fact that one-to-many relations would need to be represented as containers in the persistent object and as arrays in the XML-ed object. Many thanks.
Fabio Ceconello
Dozer's real purpose is to map from TypeA to TypeB, and to be able to store that mapping in XML configs rather than Java code, so it would be perfect for that use as well (truly mapping from one type to another).
matt b