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?
_______________________________________________
hibernate-dev mailing list
hibernate-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev

Reply via email to