[jboss-user] [EJB 3.0] - Re: Detach entities - Obtaining a clear pojo

fatbatman do-not-reply at jboss.com
Wed Sep 6 17:13:25 EDT 2006


Thanks, your code works well, I made a few adjustment though to suit my particular needs.

I think it only makes sense to use this function outside the persistance session/transaction.  This way you can decide how far you wish to traverse the object graph by populating the data you require within the session, (just as you'd do normally to avoid a LazyInitialisationException).  Then when we call the clean function outside the session we traverse until we get a LazyInitializationException, at which point we return null for that field.

I put everything within one class as I don't think we need to force people to extend a base class.  I check if an object is an entity by looking for the @Entity annotation.  If defining entities in XML this wouldn't work, but I don't   :)   
.....alternative implementation could get required object to implement some empty interface and check for that, or alternatively I'm sure there is some way of checking using some Hibernate util function, but I don't know what that is. 

Its not very well tested but it seems to work for what I need it for at the moment, I'll post bug fixes here as and when they come up.

Let me know your thoughts

James


import java.lang.annotation.Annotation;
  | import java.lang.reflect.InvocationTargetException;
  | import java.util.ArrayList;
  | import java.util.Collection;
  | import java.util.HashMap;
  | import java.util.HashSet;
  | import java.util.List;
  | import java.util.Map;
  | import java.util.Set;
  | import java.util.SortedMap;
  | import java.util.SortedSet;
  | import java.util.TreeMap;
  | import java.util.TreeSet;
  | 
  | import javax.persistence.Entity;
  | 
  | import org.apache.commons.beanutils.PropertyUtils;
  | import org.hibernate.LazyInitializationException;
  | import org.hibernate.collection.PersistentCollection;
  | 
  | public class HibernateUtils {
  | 
  | 	public static Object clean(Object obj){
  | 		return removePersistenceContext(obj, new ArrayList<Integer>());
  | 	}
  | 	
  | 	/**
  | 	 * Returns a Collection of all objects in the specified persistentCollection
  | 	 * without binding to any persistence context or session.
  | 	 * 
  | 	 * @param <T>
  | 	 * @param targetCollection
  | 	 * @param persistentCollection
  | 	 * @return
  | 	 */
  | 	public static <T> Collection<T> getCollectionItemsRemovedFromPersistenceContext(
  | 		Collection<T> targetCollection, Collection<T> persistentCollection) throws LazyInitializationException {
  | 		// If runtime type of persistentCollection is not PersistentCollection,
  | 		// take no action
  | 		if (!(persistentCollection instanceof PersistentCollection))
  | 			return persistentCollection;
  | 
  | 		// Clear existing target
  | 		targetCollection.clear();
  | 
  | 		// Place all items in persistent collection into target
  | 		for (T item : persistentCollection) {
  | 			targetCollection.add(item);
  | 		}
  | 		
  | 		// Return target
  | 		return targetCollection;
  | 	}
  | 	
  | 	/**
  | 	 * Returns a Map of all objects in the specified persistentCollection Map
  | 	 * without binding to any persistence context or session.
  | 	 * 
  | 	 * @param <T>
  | 	 * @param targetCollection
  | 	 * @param persistentCollection
  | 	 * @return
  | 	 */
  | 	public static <T, U> Map<T, U> getCollectionItemsRemovedFromPersistenceContext(
  | 			Map<T, U> targetMap, Map<T, U> persistentMap) throws LazyInitializationException {
  | 		// If runtime type of persistentCollection is not PersistentCollection,
  | 		// take no action
  | 		if (!(persistentMap instanceof PersistentCollection))
  | 			return persistentMap;
  | 
  | 		//Clear existing target
  | 		targetMap.clear();
  | 
  | 		// Place all items in persistent collection into target
  | 		for (T key : persistentMap.keySet()) {
  | 			targetMap.put(key, persistentMap.get(key));
  | 		}
  | 
  | 		// Return target
  | 		return targetMap;
  | 	}
  | 	
  | 
  | 	
  | 	/**
  | 	 * Checks if the object is an Entity bean by searching for the presence of 
  | 	 * the @Entity tag in the objects class.
  | 	 * NOTE - If you are not using annotations to define your entity objects this function will not work
  | 	 * and require an alternative implementation.
  | 	 * 
  | 	 */
  | 	protected static boolean isEntityBean(Object obj){
  | 		for(Annotation a : obj.getClass().getAnnotations()){	
  | 			if(a.annotationType()==Entity.class){
  | 				return true;
  | 			}			
  | 		}		
  | 		return false;
  | 	}
  | 	
  | 
  | 	/**
  | 	 * 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
  | 	 */
  | 	protected static Object removePersistenceContext(Object obj, Collection<Integer> visitedObjectHashCodes ){
  | 		if(obj==null){
  | 			return null;
  | 		}
  | 
  | 		if(visitedObjectHashCodes.contains(System.identityHashCode(obj))){
  | 			return obj;
  | 		}
  | 		
  | 		//Add the object's hash to the Collection of visited hash codes
  | 		visitedObjectHashCodes.add(System.identityHashCode(obj));
  | 
  | 		try{
  | 			if(obj instanceof Set){
  | 				obj = getCollectionItemsRemovedFromPersistenceContext(new HashSet(), (Set)obj);
  | 			}else if(obj instanceof SortedSet){
  | 					obj = getCollectionItemsRemovedFromPersistenceContext(new TreeSet(), (SortedSet)obj);
  | 			}else if(obj instanceof List){
  | 				obj = getCollectionItemsRemovedFromPersistenceContext(new ArrayList(), (List)obj);
  | 			}else if(obj instanceof Map){
  | 				obj = getCollectionItemsRemovedFromPersistenceContext(new HashMap(), (Map)obj);
  | 			}else if(obj instanceof SortedMap){
  | 				obj = getCollectionItemsRemovedFromPersistenceContext(new TreeMap(), (SortedMap)obj);
  | 			}else if(obj instanceof PersistentCollection){
  | 				obj = getCollectionItemsRemovedFromPersistenceContext(new ArrayList(), (Collection)obj);
  | 			}
  | 		}catch(LazyInitializationException e){
  | 			return null;		
  | 		}
  | 		
  | 		if(!isEntityBean(obj)){
  | 			return obj;
  | 		}		
  | 		
  | 		Map allMembers = getInternalMembers(obj);
  | 		for(Object member : allMembers.entrySet()){
  | 			Map.Entry m = (Map.Entry)member;
  | 			try {
  | 				try{
  | 					PropertyUtils.setProperty(obj, m.getKey().toString(), removePersistenceContext(m.getValue(), visitedObjectHashCodes));			
  | 				}catch (LazyInitializationException e){
  | 					e.printStackTrace();
  | 					PropertyUtils.setProperty(obj, m.getKey().toString(), null);
  | 				}
  | 			} catch (IllegalAccessException e) {
  | 				throw new RuntimeException(e);
  | 			} catch (InvocationTargetException e) {
  | 				throw new RuntimeException(e);
  | 			} catch (NoSuchMethodException e) {				
  | 			}
  | 		}
  | 		
  | 		return obj;
  | 	}
  | 	
  | 
  | 	/**
  | 	 * Returns a Map of all internal members of the specified object
  | 	 * 
  | 	 * @param obj
  | 	 *            The object for which to obtain internal members
  | 	 * 
  | 	 * @author ALR
  | 	 * @see http://jakarta.apache.org/commons/beanutils/
  | 	 */
  | 	protected static Map getInternalMembers(Object obj){
  | 		try {
  | 			Map map = PropertyUtils.describe(obj);
  | 			return map;
  | 		} catch (IllegalAccessException e) {
  | 			throw new RuntimeException(e);
  | 		} catch (InvocationTargetException e) {
  | 			throw new RuntimeException(e);
  | 		} catch (NoSuchMethodException e) {
  | 			throw new RuntimeException(e);
  | 		}		
  | 	}
  | 	
  | }

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3969885#3969885

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3969885



More information about the jboss-user mailing list