algumas discussoes em foruns chegamos a essa solucao : import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.Hibernate; import org.hibernate.proxy.HibernateProxy; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlTransient; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class HibernateDetachUtility { private static final Log LOG = LogFactory.getLog(HibernateDetachUtility.class); public static enum SerializationType { SERIALIZATION, JAXB } public static void nullOutUninitializedFields(Object value, SerializationType serializationType) throws Exception { long start = System.currentTimeMillis(); Set<Integer> checkedObjs = new HashSet<Integer>(); nullOutUninitializedFields(value, checkedObjs, 0, serializationType); long duration = System.currentTimeMillis() - start; if (duration > 1000) { LOG.info("Detached [" + checkedObjs.size() + "] objects in [" + duration + "]ms"); } else { LOG.debug("Detached [" + checkedObjs.size() + "] objects in [" + duration + "]ms"); } } private static void nullOutUninitializedFields(Object value, Set<Integer> nulledObjects, int depth, SerializationType serializationType) throws Exception { if (depth > 50) { LOG.warn("Getting different object hierarchies back from calls: " + value.getClass().getName()); return; } if ((value == null) || nulledObjects.contains(System.identityHashCode(value))) { return; } nulledObjects.add(System.identityHashCode(value)); if (value instanceof Object[]) { Object[] objArray = (Object[]) value; for(int i = 0; i < objArray.length; i++) { nullOutUninitializedFields(objArray[i], nulledObjects, depth +1, serializationType); } } else if (value instanceof Collection) { // Null out any entries in initialized collections for (Object val : (Collection) value) { nullOutUninitializedFields(val, nulledObjects, depth + 1, serializationType); } } else if (value instanceof Map) { for (Object key : ((Map)value).keySet()) { nullOutUninitializedFields(((Map)value).get(key), nulledObjects, depth+1, serializationType); nullOutUninitializedFields(key, nulledObjects, depth+1, serializationType); } } if (serializationType == SerializationType.JAXB) { XmlAccessorType at = value.getClass().getAnnotation(XmlAccessorType.class); if (at != null && at.value() == XmlAccessType.FIELD) { //System.out.println("----------XML--------- field access"); nullOutFieldsByFieldAccess(value, nulledObjects, depth, serializationType); } else { //System.out.println("----------XML--------- accessor access"); nullOutFieldsByAccessors(value, nulledObjects, depth, serializationType); } } else if (serializationType == SerializationType.SERIALIZATION) { // System.out.println("-----------JRMP-------- field access"); nullOutFieldsByFieldAccess(value, nulledObjects, depth, serializationType); } } private static void nullOutFieldsByFieldAccess(Object object, Set<Integer> nulledObjects, int depth, SerializationType serializationType) throws Exception { Class tmpClass = object.getClass(); List<Field> fieldsToClean = new ArrayList<Field>(); while (tmpClass != null && tmpClass != Object.class) { Collections.addAll(fieldsToClean, tmpClass.getDeclaredFields()); tmpClass = tmpClass.getSuperclass(); } nullOutFieldsByFieldAccess(object, fieldsToClean, nulledObjects, depth, serializationType); } @SuppressWarnings("unchecked") private static void nullOutFieldsByFieldAccess(Object object, List<Field> classFields, Set<Integer> nulledObjects, int depth, SerializationType serializationType) throws Exception { boolean accessModifierFlag = false; for (Field field : classFields) { accessModifierFlag = false; if (!field.isAccessible()) { field.setAccessible(true); accessModifierFlag = true; } Object fieldValue = field.get(object); if (fieldValue instanceof HibernateProxy) { Object replacement = null; if (fieldValue.getClass().getName().contains("javassist")) { Class assistClass = fieldValue.getClass(); try { Method m = assistClass.getMethod("writeReplace"); replacement = m.invoke(fieldValue); String className = fieldValue.getClass().getName(); className = className.substring(0, className.indexOf("_$$_")); if (!replacement.getClass().getName().contains("hibernate")) { nullOutUninitializedFields(replacement, nulledObjects, depth+1, serializationType); field.set(object, replacement); } else { replacement = null; } } catch (Exception e) { System.out.println("Unable to write replace object " + fieldValue.getClass()); } } if (replacement == null) { field.set(object, replacement); /*String className = ((HibernateProxy) fieldValue).getHibernateLazyInitializer().getEntityName(); Class clazz = Class.forName(className); Class[] constArgs = {Integer.class}; Constructor construct = null; try { construct = clazz.getConstructor(constArgs); replacement = construct.newInstance((Integer) ((HibernateProxy) fieldValue).getHibernateLazyInitializer().getIdentifier()); field.set(object, replacement); } catch (NoSuchMethodException nsme) { try { Field idField = clazz.getDeclaredField("id"); Constructor ct = clazz.getDeclaredConstructor(); ct.setAccessible(true); replacement = ct.newInstance(); if