[hibernate-dev] remove object from collection without collection fetching

Renat usgraf at ngs.ru
Wed May 14 23:56:17 EDT 2008


Hello,

I have bi-directional association between parent/child. 
Parent can have too many children and I want to add and 
remove to "children" (inverse=true) collection without 
loading collection.
"children" collection mapped as <bag>. With adding to 
collection I have no problem, but when I try to remove 
from this collection, collection perform initialization.

Java class:

public class MyObject
{
    private Long id;
    private MyObject parent;
    private Collection< MyObject > children = new 
ArrayList< MyObject >();

    public MyObject()
    {
    }

   public void addChild( MyObject object )
   {
     object.parent = this;
     children.add( object );
   }

   public void removeChild( KAObject object )
   {
     object.parent = null;
     children.remove( object ); // initialization of 
collection. it is strange, because too many children.
   }

}

Database:

table: my_object
fields:
- id
- parent_id


Mapping:

<hibernate-mapping>

<class name="MyObject" table="my_object" >
     <id name="id" column="id" type="long">
       <generator class="sequence">
         <param name="sequence">my_object_seq</param>
       </generator>
     </id>
     <many-to-one name="parent" class="MyObject" 
column="parent_id" lazy="no-proxy" cascade="evict" 
access="field" />
     <bag name="children" inverse="true" lazy="true" 
cascade="all-delete-orphan" access="field">
       <key column="parent_id" />
       <one-to-many class="MyObject" />
     </bag>
</class>

I want for example move child to another parent.

MyObject newParent = session.get(MyObject.class, 1);

MyObject child = session.get(MyObject.class, 2);

MyObject oldParent = myObject.getParent();

oldParent.removeChild(child); // initialization of 
collection. it is strange, because too many children.
newParent.addChild(child) // no initialization


Why PersistentBag.remove is not implemented like 
PersistentBag.add ?

	public boolean add(Object object) {
		if ( !isOperationQueueEnabled() ) {
			write();
			return bag.add(object);
		}
		else {
			queueOperation( new SimpleAdd(object) );
			return true;
		}
	}

	public boolean remove(Object o) {
		initialize( true );
		if ( bag.remove( o ) ) {
			dirty();
			return true;
		}
		else {
			return false;
		}
	}

I think problem, that interface of 
Collection.remove(Object) should return result of remove. 
But what aboutm if I never use this result.
I can write own implementation of PersistentBag with 
overrided method remove. and use it in User Collection 
Type.

   public boolean remove( Object o )
   {
     if ( !isOperationQueueEnabled() )
     {
       write();
       return bag.remove( o );
     }
     else
     {
       queueOperation( new SimpleRemove( o ) );
       return true; // this result can be wrong
     }
   }
   
   final class SimpleRemove implements DelayedOperation {
     private Object value;

     public SimpleRemove(Object value) {
       this.value = value;
     }
     public void operate() {
       bag.remove(value);
     }
     public Object getAddedInstance() {
       return null;
     }
     public Object getOrphan() {
       return value;
     }
   }

In this implementation I should always remember, that 
result of Collection.remove(Object) can be wrong and never 
use it.
May be anybody know another solution?



More information about the hibernate-dev mailing list