Hi Alex
I have donde this with many projects. The problem with Hibernate and
any framework that serializes POJOs (GWT, WebServices, JSON, etc) is
that Hibernate does not return POJOs, but Proxies of your POJOs. So
basically the solution to this problem is to clean your objects
returned by Hibernate to convert them to POJOs. I've seen examples
from Google that they just basically write code to create the POJO's
again and set the attributes but we prefer to use a Cleaner class that
automatically does this job.
The other problem is that you have to be careful when you save because
you are passing to hibernate an object that is not a proxy. This
causes problems when you're saving an object with collections. The
objects in the new collection will be inserted but the old objects
will not be deleted from the database. So one workaround is to load
the object from the database and set the attributes, clean the
collections (this will erase the objects from the database), and add
the new objects.
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.List;
import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.EntityMode;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.proxy.HibernateProxyHelper;
import java.io.Serializable;
import java.sql.Blob;
import java.util.*;
import org.apache.log4j.Logger;
import org.hibernate.proxy.HibernateProxy;
public class HibernateCleaner {
private static final Logger logger =
Logger.getLogger(HibernateCleaner.class);
public static Object clean(Session session, Object obj) throws Exception {
return (clean(session, obj, new HashMap<Class, Map<Object, Object>>()));
}
private static Object clean(Session session,
Object obj,
Map<Class, Map<Object, Object>>
visitedObjects) throws Exception {
Object newObj, value = null, cleanValue = null;
Map.Entry m;
Class clazz;
Object[] array;
Collection collection;
Map map;
PropertyDescriptor[] descriptors;
String property;
ClassMetadata clazzMetaData;
Map<Object, Object> visitedObjectsInClass;
int index, length, hashCode;
if (obj == null)
return (null);
if ((obj instanceof Boolean) || (obj instanceof Number) ||
(obj instanceof Character) || (obj instanceof String) ||
(obj instanceof Blob) || (obj instanceof InputStream))
return (obj);
if (obj instanceof Date)
return (new Date (((Date) obj).getTime()));
if (obj instanceof Calendar)
return (((Calendar) obj).clone());
if (obj instanceof Object[]) {
array = (Object[]) ((Object[]) obj).clone();
length = array.length;
for (index = 0; index < length; index++)
array[index] = clean(session, array[index], visitedObjects);
return (array);
}
if (obj instanceof Object[]) {
array = (Object[]) ((Object[]) obj).clone();
length = array.length;
for (index = 0; index < length; index++)
array[index] = clean(session, array[index], visitedObjects);
return (array);
}
if (obj instanceof Collection) {
collection = createCollection((Collection) obj);
if (Hibernate.isInitialized(obj)) {
for (Object member: (Collection) obj)
collection.add (clean(session, member, visitedObjects));
}
return (collection);
}
if (obj instanceof Map) {
map = createMap((Map) obj);
if (Hibernate.isInitialized(obj)) {
for (Object member: ((Map)obj).entrySet()) {
m = (Map.Entry) member;
clean(session, m.getKey(), visitedObjects);
clean(session, m.getValue(), visitedObjects);
map.put (m.getKey(), m.getValue());
}
}
return (map);
}
if (obj instanceof HibernateProxy) {
clazz = HibernateProxyHelper.getClassWithoutInitializingProxy(obj);
} else {
clazz = obj.getClass();
}
visitedObjectsInClass = visitedObjects.get(clazz);
if (visitedObjectsInClass == null) {
visitedObjectsInClass = new HashMap<Object, Object>();
visitedObjects.put(clazz, visitedObjectsInClass);
} else if (visitedObjectsInClass.containsKey(obj)) {
return visitedObjectsInClass.get(obj);
}
newObj = clazz.newInstance();
visitedObjectsInClass.put(obj, newObj);
if (!Hibernate.isInitialized(obj)) {
if (session != null) {
clazzMetaData =
session.getSessionFactory().getClassMetadata(newObj.getClass());
Serializable id = clazzMetaData.getIdentifier(obj,
EntityMode.POJO);
clazzMetaData.setIdentifier(newObj, id, EntityMode.POJO);
}
} else {
descriptors = PropertyUtils.getPropertyDescriptors(newObj);
length = descriptors.length;
for (index = 0; index < length; index++) {
property = descriptors[index].getName();
if (!property.equals("class")) {
try {
value = PropertyUtils.getProperty(obj, property);
cleanValue = clean(session, value, visitedObjects);
PropertyUtils.setProperty(newObj, property, cleanValue);
} catch (NoSuchMethodException e) {
} catch (Exception e) {
if (logger.isInfoEnabled()) logger.info("Error
Clean: " + obj.getClass() + " - " + property + " - " +
value.getClass() + " - " + cleanValue.getClass());
throw(e);
}
}
}
}
return (newObj);
}
private static Collection createCollection(Collection obj) throws
Exception {
Collection newObj = null;
if (obj instanceof SortedSet)
newObj = new TreeSet ();
else if (obj instanceof Set)
newObj = new HashSet ();
else
newObj = new ArrayList ();
return (newObj);
}
private static Map createMap(Map obj) throws Exception {
Map newObj = null;
if (obj instanceof SortedMap)
newObj = new TreeMap ();
else
newObj = new HashMap ();
return (newObj);
}
}
Hope this helps.
Regards,
Néstor Boscán
--
You received this message because you are subscribed to the Google Groups
"Google Web Toolkit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-web-toolkit?hl=en.