[jboss-user] [EJB 3.0] - Re: Detach entities - Obtaining a clear pojo
dietice
do-not-reply at jboss.com
Sun Jul 6 17:09:33 EDT 2008
Since the challenge still exists, here is an even further improved version.
The behaviour is the same, simply some performance improvements were added.
package org.hibernate.collection;
|
| import java.lang.reflect.InvocationTargetException;
| import java.util.Collection;
| import java.util.HashSet;
| import java.util.Map;
|
| import org.apache.commons.beanutils.PropertyUtils;
| import org.hibernate.LazyInitializationException;
|
| /**
| * Some utility methods to get a complete clean POJO from an entity bean with hibernate
| * specific fields stripped out. Note this class is not meant as a way of avoid
| * LazyInitializationException's.
| * Its purpose to strip out data before sending the object to a remote client so that
| * does not have knowledge of hibernate classes.
| * @author ALR 5/9/2006
| * @author modified by James Adams 6/9/2006, 7/9/2006
| * @author me 7/6/2008
| */
| public final class HibernateCleaner
| {
| /**
| * Traverse through the object removing all fields of type
| * org.hibernate.collection.PersistentCollection. by following all bean style get* methods.
| * <p>
| * <b>Note</b> the object cannot be reattached after calling this method.
| *
| * @param obj the object to clean
| */
| public static void clean(final Object obj)
| {
| try
| {
| removePersistenceContext(obj, new HashSet<Integer>());
| }
| catch (final IllegalAccessException e)
| {
| throw new RuntimeException(e);
| }
| catch (final InvocationTargetException e)
| {
| throw new RuntimeException(e);
| }
| catch (final NoSuchMethodException e)
| {
| throw new RuntimeException(e);
| }
| }
|
| /**
| * Checks if the object MIGHT contain PersistentCollection fields by checking if its not a
| * primitive, or if its in package java.* or javax.*.
| *
| * <p>
| * <b>NOTE</b> This relies on there not being an entity within those packages.
| * A more conservative approach is to only check if its a primitive.
| * @param obj the object to check
| * @author James Adams
| */
| public static boolean couldObjectContainPersistentCollections(final Object obj)
| {
| if (obj == null) return false;
|
| final Class clazz = obj.getClass();
|
| if (clazz.isPrimitive()) return false;
|
| final String className = clazz.getName();
|
| //TODO - This is not fool proof and relies on people not using package with names below.
| //More conservative approach is to remove this
| if (className.startsWith("java.") || className.startsWith("javax.")) return false;
|
| return true; //If we got here it might be a hibernate persisted object
| }
|
| /**
| * Because this class is in package org.hibernate.collection this method
| * allows us to access the inner protected fields of the hibernate collections
| * @param obj
| * @return The inner collection object of the PersistentCollection parameter
| * @author James Adams
| */
| private static Object getInnerCollection(final PersistentCollection obj)
| {
| if (obj instanceof PersistentBag)
| return ((PersistentBag) obj).bag;
| else if (obj instanceof PersistentList)
| return ((PersistentList) obj).list;
| else if (obj instanceof PersistentSet)
| return ((PersistentSet) obj).set;
| else if (obj instanceof PersistentMap)
| return ((PersistentMap) obj).map;
| else if (obj instanceof PersistentSortedMap)
| return ((PersistentSortedMap) obj).map;
| else if (obj instanceof PersistentSortedSet)
| return ((PersistentSortedSet) obj).set;
| else
| return null;
| }
|
| /**
| * If the specified object's identity hash code is not in the specified
| * collection of visited hash codes, removes of all data binding the object
| * (and its members) to a specific persistence context, leaving intact only
| * model-centric data
| *
| * @param visitedObjectHashCodes
| * @param obj
| * @author ALR
| * @author James Adams, modified 6/9/2006,7/9/2006
| * @throws NoSuchMethodException
| * @throws InvocationTargetException
| * @throws IllegalAccessException
| */
| private static Object removePersistenceContext(Object obj, //
| final Collection<Integer> visitedObjectHashCodes) //
| throws IllegalAccessException, InvocationTargetException, NoSuchMethodException
| {
| if (obj == null) return null;
|
| final Integer hashCode = System.identityHashCode(obj);
|
| if (visitedObjectHashCodes.contains(hashCode)) return obj;
|
| //Add the object's hash to the Collection of visited hash codes
| visitedObjectHashCodes.add(hashCode);
|
| try
| {
| // If runtime type of persistentCollection is PersistentCollection we get the
| // inner collection from within the hibernate proxy
| if (obj instanceof PersistentCollection)
| {
| obj = getInnerCollection((PersistentCollection) obj);
| }
| }
| catch (final LazyInitializationException e)
| {
| return null;
| }
|
| if (obj == null) return null;
|
| if (obj instanceof Collection)
| {
| for (final Object o : (Collection< ? >) obj)
| {
| //recurse into each element of the collection. We don't need to set the value of
| //the object in the Collection as the reference will be adjusted, doing so within
| //this iterable loop would result in a ConcurrentModificationException anyway.
| removePersistenceContext(o, visitedObjectHashCodes);
| //TODO - Does Hibernate support Collections of primitives? As this will not work
| // when the Collection is of types that Java does not pass by reference;
| // primitives, String, Integer, Float etc.
| // In this case we need to create a new Collection and populate it.
| }
| }
| else if (!couldObjectContainPersistentCollections(obj))
| return obj;
| else
| {
| @SuppressWarnings("unchecked")
| final Map<String, Object> allMembers = PropertyUtils.describe(obj);
| for (final Map.Entry<String, Object> member : allMembers.entrySet())
| {
| final Object propertyValue = member.getValue();
| try
| {
| final Object cleanedValue = removePersistenceContext(propertyValue, //
| visitedObjectHashCodes);
|
| // avoid costly calls via reflection if the value has not been modified
| if (cleanedValue != propertyValue)
| {
| PropertyUtils.setProperty(obj, member.getKey(), cleanedValue);
| }
| }
| catch (final LazyInitializationException e)
| {
| PropertyUtils.setProperty(obj, member.getKey(), null);
| }
| }
| }
| return obj;
| }
|
| private HibernateCleaner()
| {
| // nothing
| }
| }
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4162685#4162685
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4162685
More information about the jboss-user
mailing list