-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 17 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Trouble with delete using cascade="all-delete-orphan&qu
PostPosted: Fri Feb 27, 2004 7:08 pm 
Newbie

Joined: Fri Feb 27, 2004 4:02 pm
Posts: 6
I am having trouble with cascade deletes using the all-delete-orphan option.

Here is the situation. I load an object that contains a bi-directional parent child relationship in one session and feed it to my presentation layer. The user makes modifications to the data, which include deleting children, and then the a new copy of the modified data object is passed to the saveOrUpdate method in a new session. What I want to happen is the child object that was deleted from the child collection to be deleted from the database. This is not happening. No errors occur, but the child object is left intact in the database. Am I doing something wrong here?

Mapping...

Parent
<map name="children"
table="CHILD"
lazy="false"
sort="unsorted"
inverse="true"
cascade="all-delete-orphan">
<key column="PARENT_ID"/>
<one-to-many class="Child">
</map>

Child
<many-to-one name="parent"
class="Parent"
cascade="none"
outer-join="auto"
update="true"
insert="true"
column="PARENT_ID"
not-null="true">
</many-to-one>

Parent object code...

void addChild(Child child)
{
children.put(child.getKey(), child);
child.setParent(this);
}

void removeChild(Child child)
{
children.remove(child.getKey());
child.setParent(null);
}

Example client code ...

parent = new Parent();

// load parent with data from form
parent.setData(data);
parent.addChild(child1);
parent.addChild(child2);

// process any delete requests
parent.removeChild(childKeyForDelete);

sess = factory.openSession();
trans = sess.beginTransaction();
sess.delete(parent);
trans.commit();
sess.close();


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 27, 2004 9:42 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
all-delete-orphan only works while to object is attatched to a session.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 01, 2004 12:28 pm 
Newbie

Joined: Fri Feb 27, 2004 4:02 pm
Posts: 6
Ok. This is a bit of a hack, but I'm trying code around my problem with cascade-delete-orphan. However, when I execute this code, I get the following exception. How am I "dereferencing" the collection? I checked the JDK 1.4 implementation of AbstractMap.putAll and it simply iterates over the given map and copies in the key/value mappings.

Exception

net.sf.hibernate.HibernateException: You may not dereference a collection with cascade="all-delete-orphan"
at net.sf.hibernate.impl.SessionImpl.updateUnreachableCollection(SessionImpl.java:2885)
at net.sf.hibernate.impl.SessionImpl.flushCollections(SessionImpl.java:2754)
at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2225)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2203)
at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)

Code

Code:
sess = sessionFactory.openSession();
trans = sess.beginTransaction();
if( parent.getId() != null )
{
  loaded = (Parent) sess.load(ParentImpl.class, parent.getId());
  loaded.copyFrom(parent);
  sess.update(loaded);
} else
{
  sess.save(parent);
}
trans.commit();


Code:
public void copyFrom(Parent parent)
{
  // copy all of the target parent's attributes
  setData(data);

  // remove children that are not part
  // of the parent we are copiing
  Iterator it = children.keySet().iterator();
  String key;
  while( it.hasNext() )
  {
    key = (String) it.next();
    if( ! parent.getChildren().containsKey(key) )
    {
      children.remove(key);
    }
  }

  // copy in all of the children from the
  // target parent
  children.putAll(parent.getChildren());
}


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 01, 2004 12:36 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
all-delete-orphan only works while to object is attatched to a session.


This is not correct; it even works for detached objects.


The real problem is that (as per the doco) you are never allowed to dereference a collection with all-delete-orphan. So the exception is very self-explanatory. Just don't do that.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 01, 2004 1:31 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
Quote:
This is not correct; it even works for detached objects.


Arrh, sorry for the wrong info posted.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 01, 2004 2:00 pm 
Newbie

Joined: Fri Feb 27, 2004 4:02 pm
Posts: 6
Quote:
The real problem is that (as per the doco) you are never allowed to dereference a collection with all-delete-orphan.


1) So, let's just assume for now that I don't know what it means to dereference a collection. Could you explain to me what you consider it to mean to dereference the collection?

2) Also, can you provide me a link to the documentation you are refering to? I don't see anywhere in the manual where it says that I cannot dereference a collection controlled by all-delete-orphan. In fact, the cascade example in section 9.3 shows client code directly removing an element from a Hibernate loaded collection, similiar to what I propose in my code above.

http://www.hibernate.org/hib_docs/reference/html/manipulating-data.html#manipulating-data-s11a


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 01, 2004 2:17 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
You can remove the elements from a collection, but you can't remove the collection itself from its parent element, or replace it with a new collection. I suppose in copyFrom, you are moving the collection over to a new object, which is not allowed.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 01, 2004 3:26 pm 
Newbie

Joined: Fri Feb 27, 2004 4:02 pm
Posts: 6
That makes sense. I fully understand that I am not allowed to substitute a new collection instance for the one that is pointed to by the parent object. If there were a place in the code where that was happening, I would understand the dereference exception . However, I don't see how that is possible. My code removes unwanted elements from the Map, adds uncontained transient instances to the map, updates existing persistent instances with identical transient ones.

Does the same principle of not changing objects apply to instances contained within the underlying collection? Because I am overwriting formerly persient instances in the map with identical transient instances.

The whole affect I'm trying to achieve here is that the object contained in my presentation layer gets persisted by the business layer, with all changes to the objects in the children collection getting persisted at the same time. If either of you have a suggestion as a better way to achieve this, I am more than willing to listen.

Thank you for your help.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 01, 2004 3:36 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
I suspect parent is a detatched object? Why don't you just call update(parent) without all that copying-over stuff?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 01, 2004 3:51 pm 
Newbie

Joined: Fri Feb 27, 2004 4:02 pm
Posts: 6
If by detached, you mean that I used the Session.detach() method, that is incorrect. I have no reference to the session in which the object was originally loaded. My understanding is that Hibernate considers this object transient. Correct?

When I pass the object from the UI to the business tier, using the saveOrUpdate method, it persists all of the properties, including additions to the child collection, but does not persist deletions in the child collection. My code above for copying the properties was an attempt to manipulate an object that was attached to a session so that I could get the benefits of the cascading delete.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 01, 2004 3:55 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
If you use cascade=all-delete-orphan and do not exchange the collection against something else, session.update should also remove deleted children, even in the object comes from another session. Does this really not work?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 01, 2004 4:51 pm 
Newbie

Joined: Fri Feb 27, 2004 4:02 pm
Posts: 6
Yes, it works if the objects are the original copies. The way things currently work in my application, I make a new copy of the object every time a form is submitted by the web tier.

The reason for my copy logic above was to try to simulate the situation you describe. By loading an object and copying properties into it from a web tier's instance, I thought I could guarantee that the objects being manipulated by Hibernate were under Hibernate's control. However, I cannot get past the error that says "collection cannot be dereferenced."


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 10:16 am 
Beginner
Beginner

Joined: Thu Aug 28, 2003 3:09 pm
Posts: 39
Location: Brazil
Hi michael,

Here, the removing of the child isn't working too. :(

I load the parent in one session, passing the result to presentation and later when I do a save or update and flush in another session with the child removed, nothing happens...

I'm using hibernate 2.1.1.

When Gavin said it works for detached objects, does he mean from a disconnected session of from a new session?

Thanks in advance


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 10:24 am 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
It should work for a disconnected object from a different session, too, if you don't change the collection. (eg only add/remove from it). If not, please submit a small reproducable test case to JIRA.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 3:54 pm 
Beginner
Beginner

Joined: Thu Aug 28, 2003 3:09 pm
Posts: 39
Location: Brazil
Hi michael.

Thanks for fast reply.

I will do some other tests and will try to create a simple test case.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 17 posts ]  Go to page 1, 2  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.