Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 12 posts ] 
Author Message
 Post subject: Deleting entities and their relationships
PostPosted: Mon Sep 15, 2003 7:43 pm 
Beginner
Beginner

Joined: Mon Sep 15, 2003 6:28 pm
Posts: 26
From a #hibernate irc conversation today:

You have two entities, EntityA and EntityB. They have a bidirectional many-to-many relationship, EntityB


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 15, 2003 9:34 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
The answer is "yes" to the first, and "no" to the second.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2003 3:19 pm 
Beginner
Beginner

Joined: Mon Sep 15, 2003 6:28 pm
Posts: 26
gavin wrote:
The answer is "yes" to the first, and "no" to the second.


Is there any plan to make this behavior more consistent?

In the case of the second situation (deleting the inverse entity), is there any efficient way to delete relationship participation without resorting to JDBC?

Thanks,
Jeff


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2003 3:39 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
How is this inconsistent??

The semantics of inverse="true" are currently quite clear. i.e. Don't propagate changes made to "this end" of the association.


No, I will not be changing anything.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2003 3:48 pm 
Beginner
Beginner

Joined: Mon Sep 15, 2003 6:28 pm
Posts: 26
gavin wrote:
How is this inconsistent??

The semantics of inverse="true" are currently quite clear. i.e. Don't propagate changes made to "this end" of the association.

No, I will not be changing anything.



Then what should we do for the use case I described?

EntityA many-to-many EntityB, EntityB is inverse

I want to delete an instance of EntityB.

Jeff


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2003 3:59 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
iterate over the associated EntityB instances and remove the association at that end. This is quite consistent with how other one-to-many bidirectional associations work.


Now, note: for many-to-many associations, you don't necessarily need to do the inverse="true" thing. You can make it work perfectly well, leaving both ends inverse="false". But then you need to make sure you don't change both ends of the association in one transaction.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2003 4:25 pm 
Beginner
Beginner

Joined: Mon Sep 15, 2003 6:28 pm
Posts: 26
Ok, cool. Don't use inverse for many-to-many, that makes sense.

Now to make it more complicated:

EntityA has a Map of EntityB to a component.

I want to delete an instance of EntityB.

How can I do this?

This is a real-world problem for me which I haven't addressed yet. I've been assuming "delete the relationship with JDBC, delete the entity with Hibernate, and evict the relationship cache", which is inelegant but ok for my purposes.

Jeff


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 16, 2003 9:21 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
you should *still* be able to make this association bidirectional. But map the reverse association as a simple many-to-many Set, and do use inverse="true". That way, you can "get to the other end", and then remove the association from the other end.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 17, 2003 5:28 pm 
Beginner
Beginner

Joined: Mon Sep 15, 2003 6:28 pm
Posts: 26
gavin wrote:
you should *still* be able to make this association bidirectional. But map the reverse association as a simple many-to-many Set, and do use inverse="true". That way, you can "get to the other end", and then remove the association from the other end.


That would mean loading every instance of EntityA (and fully populating its Map) which has a relationship with the EntityB that I'm deleting... that could be millions of EntityA objects, each of which will likely have 100-200 map entries. Ouch.

Would it be possible to achieve the same effect (without adding bidirectionality) using a query like this?

Code:
List fixList = sess.find("from EntityA a where a.theMapOfBs[?] is not null", b.getId(), Hibernate.LONG);


Not that it would solve the performance problem...

Jeff


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 26, 2003 3:09 am 
Beginner
Beginner

Joined: Fri Sep 26, 2003 2:50 am
Posts: 32
I have a demo to test deleting many-to-many entity,it like following:

Code:
//this setting is for entity Operation
<set name="users" table="T_UserRights" lazy="true" inverse="true" cascade="none">
      <key column="OperID"/>
      <many-to-many class="test.User" column="UserID" outer-join="auto"/>
</set>

//This setting is for entity User
<set name="operations" table="T_UserRights" lazy="true" cascade="none">
  <key column="UserID"/>
  <many-to-many class="test.Operation" column="OperID" outer-join="auto"/>
</set>


T_User: UserID UserName ...
T_Operation: OperID OperName ...
T_UserRights: UserID OperID

Now, I get a User instance from hibernate, and delete it, this code is:
Code:
//session is a variable of Session class
User user = (User) session.load(User.class, "test");
Transaction tx = session.beginTransaction();
session.delete(user);
session.flush();
tx.commit();


when the program run these codes. it throws the following exception:
Code:
net.sf.hibernate.HibernateException: Flush during cascade is dangerous - this might occur if an object was deleted and then re-saved by cascade (remove deleted object from associations)

   at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2174)

   at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:626)

   at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1216)

   at net.sf.hibernate.engine.Cascades$5.cascade(Cascades.java:105)

   at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:280)

   at net.sf.hibernate.engine.Cascades.cascadeCollection(Cascades.java:373)

   at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:296)

   at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:331)

   at net.sf.hibernate.impl.SessionImpl.preFlushEntities(SessionImpl.java:2470)

   at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2188)

   at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2177)

   at test.Test.run(Test.java:132)

   at test.Test.main(Test.java:38)


please help me! thanks!


Top
 Profile  
 
 Post subject: have u tried
PostPosted: Fri Sep 26, 2003 4:35 am 
Beginner
Beginner

Joined: Mon Sep 22, 2003 7:16 am
Posts: 25
setting both inverse=false


Top
 Profile  
 
 Post subject: Re: have u tried
PostPosted: Fri Sep 26, 2003 4:42 am 
Beginner
Beginner

Joined: Fri Sep 26, 2003 2:50 am
Posts: 32
csmklee wrote:
setting both inverse=false


I have tried it to set both inverse=false, the result is same!

BTW, I set the 'set' properties like the examples Author/Work in reference manual CHAP16, it can not work too.

UNHAPPY!!!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

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.