[jboss-user] [EJB 3.0] - Re: Detach entities - Obtaining a clear pojo
ALRubinger
do-not-reply at jboss.com
Tue Sep 5 16:41:25 EDT 2006
Allright; I've got something. Would love to hear opinions as to whether this makes for good design, and I'll probably cross-post this somewhere on the Hibernate forums to get thoughts from there...
Given a static utility method (code all below) that will return a non-Hibernate Collection of Entities, I had wanted to create a method that would strip out all Hibernate Collections from a POJO, like:
Object newPojo = PersistenceUtils.removePersistenceContext(myPojo);
...however, could not figure any intelligent way to instruct the method as to how deeply it should be traversing its own graph to look for Hibernate classes.
So I restructured a bit (this is the part on which I'm wavering) to place the Hibernate-stripping method in an assumed Base Class for all entities. So the call now looks more like:
myPojo.removePersistenceContext();
I don't like that this solution requires a base entity class.
But it works for now - curious as to anyone's thoughts.
The Utility Class:
public class PersistenceUtils {
|
| /**
| * 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> removeCollectionItemsFromPersistenceContext(
| Collection<T> targetCollection, Collection<T> persistentCollection) {
| // 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;
| }
|
| }
|
Base Entity Class (from which all EJB3 Entities inherit; relevent code only shown):
/**
| * Strips the entity of all data binding it to a specific persistence
| * context, leaving intact only model-centric data
| *
| * @author ALR
| */
| public void removePersistenceContext() {
| // Initialize
| Collection<Integer> visitedObjectHashCodes = new ArrayList<Integer>();
|
| // Run
| this.removePersistenceContext(this, visitedObjectHashCodes);
| }
|
| /**
| * 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
| */
| private Object removePersistenceContext(Object obj,
| Collection<Integer> visitedObjectHashCodes) {
|
| // Ensure the current object has not been visited
| if (visitedObjectHashCodes.contains(System.identityHashCode(obj))) {
| return obj;
| }
|
| // Add the current object's hash to the Collection of visited hash codes
| visitedObjectHashCodes.add(System.identityHashCode(obj));
|
| // If the current object is of type Collection
| if (Collection.class.isInstance(obj)) {
| // Remove persistence context
| obj = PersistenceUtils.removeCollectionItemsFromPersistenceContext(
| new ArrayList(), (Collection) obj);
| }
|
| // Only traverse into types of PersistedEntity
| if (!(PersistedEntity.class.isInstance(obj))) {
| return obj;
| }
|
| // Remove persistence context of all members
| Map allMembers = this.getInternalMembers();
| for (Object member : allMembers.entrySet()) {
| Map.Entry m = (Map.Entry) member;
| try {
| PropertyUtils.setProperty((Object) obj, m.getKey().toString(),
| this.removePersistenceContext((m.getValue()),
| visitedObjectHashCodes));
| } catch (IllegalAccessException e) {
| throw new RuntimeException(e);
| } catch (InvocationTargetException e) {
| throw new RuntimeException(e);
| } catch (NoSuchMethodException e) {
| }
| }
|
| // Return
| return obj;
| }
|
| // Internal Helper Methods
| /**
| * 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 Map getInternalMembers(PersistedEntity obj) {
| try {
| // Return a map of all visible properties
| return PropertyUtils.describe(obj);
| }
| // Throw as unchecked exceptions up the stack trace
| catch (IllegalAccessException iae) {
| throw new RuntimeException(iae);
| } catch (NoSuchMethodException nsme) {
| throw new RuntimeException(nsme);
| } catch (InvocationTargetException ite) {
| throw new RuntimeException(ite);
| }
| }
|
| /**
| * Returns a Map of all internal members of this PersistedEntitys
| *
| * @author ALR
| * @see http://jakarta.apache.org/commons/beanutils/
| */
| protected Map getInternalMembers() {
| return getInternalMembers(this);
| }
Easy to use (one line of code), and it works. But I have the nagging feeling I can't be the first to have come across this, and there's a better way?
S,
ALR
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3969582#3969582
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3969582
More information about the jboss-user
mailing list