Search code examples
hibernateserializationpojo

remove Hibernate from entity pojo's?


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);
        }                       
    }
}

Solution

  • 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.