-->
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.  [ 7 posts ] 
Author Message
 Post subject: Bidirectional many-to-many - constraint violation
PostPosted: Mon Mar 01, 2004 7:15 pm 
Newbie

Joined: Wed Jan 07, 2004 1:56 pm
Posts: 14
Hi,

I am having some difficulty with a bidirectional many-to-many relationship.
I have read up on bidirectional relationships - but I am having some problem - most likely something I am doing wrong - something I misunderstand.

I have two entities that have a many-to-many relationship. Ala:

<class name="com.toot.toot.User" table="UsersSandbox" mutable="false">
...snip...
<set name="categories" lazy="false" cascade="none" table="UserCategory">
<key column="user_id"/>
<many-to-many class="com.toot.toot.Category" column="category_id"/>
</set>
</class>

<class name="com.toot.toot.Category" table="Category">
...snip...
<set name="subscribers" lazy="false" cascade="none" table="UserCategory" >
<key column="category_id"/>
<many-to-many class="com.toot.toot.User" column="user_id" />
</set>
</class>

At time=0, We have a User U and a Category C - they have been loaded by a session.find query - and they have no relationships. I want to create a bidirectional association between them.

So, I do the following:
user.getCategories().add(category);

Now, if I understand correctly, for bidirectional relationships, I also need to do the following:
category.getSubscribers().add(user);

However, this results in Hibernate trying to insert two relationships in the Join Table.... which violates our constraints.

So, I guess my question is: "What am I doing wrong?". What am I not understanding?

If I just do the 1st one, then what gets persisted to the database is correct, however, until I clear the cached values (session.clear()), and reload the entities, my category C still shows no subscribers.... :-(

Thanks.
-Nick

Using JDK1.4.2, Hib2.1.2


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 02, 2004 12:45 am 
Regular
Regular

Joined: Mon Nov 24, 2003 6:36 pm
Posts: 105
I don't think both your classes should have a many to many- only the "parent " object should have the many-many. the category should have a 1-m- not m-m.

Code should just need to add to the one set. Potentially if inverse=true, parent will need setting on child.

Good luck

James


Top
 Profile  
 
 Post subject: Eh?
PostPosted: Tue Mar 02, 2004 8:44 am 
Newbie

Joined: Wed Jan 07, 2004 1:56 pm
Posts: 14
jlawmi wrote:
I don't think both your classes should have a many to many- only the "parent " object should have the many-many. the category should have a 1-m- not m-m.


??

Not sure I understand why. Can you point me to some doco?

Cheers,
Nick


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 02, 2004 9:06 am 
Regular
Regular

Joined: Mon Nov 24, 2003 6:36 pm
Posts: 105
Think I was wrong- looks like you can have a set on both ends. Anyway, the example I would use is author-work example:
http://www.hibernate.org/hib_docs/refer ... xamples-s1

Notice there is a table called "author_work" that is not in the object model.

Unfortuneately, seems that there is no code w/ this example, so I'm not sure you would add to both the sets...

James


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 02, 2004 11:54 am 
Newbie

Joined: Wed Jan 14, 2004 3:56 pm
Posts: 7
Location: Ann Arbor, MI, USA
Author/Work is the appropriate example. The Hibernate solution to this problem seems to be that, in a bi-directional many-to-many relationship, one side has to be "less equal" than the other. One side has more responsibility for managing the relation.

Add inverse = "true" to the Category side:
Code:
<class name="com.toot.toot.Category" table="Category">
...snip...
  <set name="subscribers" lazy="false" inverse="true" cascade="none"
    table="UserCategory" >
    <key column="category_id"/>
    <many-to-many class="com.toot.toot.User" column="user_id" />
  </set>
</class>

and then
Code:
user.getCategories().add(category);
category.getSubscribers().add(user);

will not result in the duplicate relation being added to the UserCategory table.

This is because inverse="true" says that Category does not have responsibility for creating the SQL that manages the relation. User does have that responsibility becuase inverse="false" is the default.

More about inverse is at http://www.hibernate.org/155.html

Will


Top
 Profile  
 
 Post subject: Thanks!
PostPosted: Tue Mar 02, 2004 11:39 pm 
Newbie

Joined: Wed Jan 07, 2004 1:56 pm
Posts: 14
Thanks v.much Will.

I think I get it now.

-Nick


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 02, 2004 11:43 pm 
Newbie

Joined: Wed Jan 07, 2004 1:56 pm
Posts: 14
jlawmi wrote:
I'm not sure you would add to both the sets...


I think that the point about Hibernate (took me a little bit for the penny to drop) is that it is "Idiomatic Persistance".

Adding to only one set wouldnt make sense in Java for a bidirectional relationship. So if Hibernate were to do some magic behind the scenes then it would be "intrusive". Ie your code wouldnt work without Hibernate (like with CMP/CMR).

So, you *want* to add to both collections - but you want Hibernate to only do the one persistance-related update/insert.

The key seems to be inverse="true"

-Nick


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.