Hibernate version:3.2.6
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:
Code:
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:
Code:
<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>
</hibernate-mapping>
I want for example move child to another parent.
Code:
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(Object) is not implemented like
PersistentBag.add(Object) ?
Code:
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 about if I never use this result.
I can write own implementation of
PersistentBag with overrided method remove. and use it in
UserCollectionType.
Code:
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.
How do you think, this solution will be always work?
May be anybody know another solution?