4

I've been experimenting on removing Hibernate specific details from entity pojo's (e.g. when I need to serialize them and send to remote machines), and following is the code I came up with. Its 'initializeAndUnproxy()' is taken from one of the answers that Bozho gave: Converting Hibernate proxy to real object and I modified it to call a recursive method in it.

I would like your comments on this code about its shortcomings. E.g. it won't remove 'PersistentSet' kind of types from it. So what improvements would you suggest?

static <T> T initializeAndUnproxy(T entity) throws IllegalArgumentException, IllegalAccessException
{
    if(entity == null)
    {         
        throw new NullPointerException("Entity passed for initialization is null");     
    } 

    Hibernate.initialize(entity);       
    T ret = entity;

    if(entity instanceof HibernateProxy)
    {           
        ret = (T)((HibernateProxy)entity).getHibernateLazyInitializer().getImplementation();
        initializeRecursively(ret);         
    }

    return ret;
}

static void initializeRecursively(Object entity) throws IllegalArgumentException, IllegalAccessException
{
    Class<?> clazz = entity.getClass();
    Field[] fields = clazz.getDeclaredFields();

    for(Field field : fields)
    {
        field.setAccessible(true);          
        Object obj = field.get(entity);                     
        Hibernate.initialize(obj);

        if(obj instanceof HibernateProxy)
        {                               
            obj = ((HibernateProxy)obj).getHibernateLazyInitializer().getImplementation();
            field.set(entity, obj);     
            initializeRecursively(obj);
        }           
        if(obj instanceof LazyInitializer)
        {                       
            obj = ((LazyInitializer)obj).getImplementation();   
            initializeRecursively(obj);
        }                       
    }
}
Community
  • 1
  • 1
shrini1000
  • 6,670
  • 11
  • 54
  • 93

2 Answers2

1

Object cloning maybe? Clone every object you want to serialize and send over the network. You do have to write a clone method although you wont have an additional DTO class for every POJO

user979051
  • 1,187
  • 2
  • 15
  • 34
-1

I don't see the point. If I understand correctly

  • the remote client still has to have Hibernate jars in its classpath,
  • all this does is to recursively initialize all the toOne associations of the entity

So, you'll probably still have lazy loading exceptions because of uninitialized proxies in the collections. You'll probably transfer more data than necessary to the remote client, which probably doesn't need all the toOne associations and all the collections initialized. Doing that will of course generate a whole lot of additional queries to the database.

My point of view is that

  • either the client is tightly coupled to the server, may be dependent on Hibernate, and uses detached Hibernate entities. And you should only initialize what the client needs to be initialized
  • or the client ios loosely coupled and may not be dependent on Hibernate, and you should then transfer common DTOs, and transform your entities into DTOs.
JB Nizet
  • 633,450
  • 80
  • 1,108
  • 1,174
  • well, the point is that I need to serialize the entire graph of a Hibernate pojo object for sending it to a remote machine. That machine won't have any Hibernate jars and hence I need to remove all traces of Hibernate from that object graph. The code I showed is an attempt to do it, but it's not complete because it doesn't remove things like persistent sets. So how can this code be improved? – shrini1000 Dec 16 '11 at 10:21
  • As I said, I think that in 99% of the cases, the client doesn't need the whole graph. A whole graph of objects, recursively, with bidirectional associations, could make you load half of your database. I would make the client define a DTO containing what it really needs, and populate this DTO from the entities. – JB Nizet Dec 16 '11 at 11:05
  • But isn't DTO an anti-pattern? Plus, if the objects and their associations are small, won't it be reasonable to de-Hibernate them and then send them? – shrini1000 Dec 16 '11 at 11:48
  • DTO is an anti-pattern when it's used to transfer information that could be sent as entities between two parts of a single application. You seem to have two different, loosely-coupled applications. A DTO looks right to me. If the entities are small, it will be easier to transform them to DTOs. – JB Nizet Dec 16 '11 at 13:42