-->
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: Hibernate Mapping - Many to Many -- How to....
PostPosted: Thu Feb 23, 2006 3:07 pm 
Newbie

Joined: Sun Sep 18, 2005 6:34 pm
Posts: 12
Hibernate version: 3.1.2

Im trying configure Hibernate to work with some existing data structures and I am having difficultly capturing the following relationship in my Hibernate mappings.

My Model is as follows...

Table 1 {User}---> contains user information
Table 3 {UserGroup} --> contains Usergroup Names
Table 2 {Join_Users_to_Usergroup} --> contains relationship information of user to Usergroup memebership and Vice Versa

When I generate my POJOs I would like to access the data in the following manner...

user.getUserGroups()
user.setUserGroups()
usergroup.getUsers()
usergroup.setUsers()

....and would like to cascade Usergroup relationships is a usergroup or user gets deleted.

How would I alter my mappings to have hibernate do this for me?

Thanks,
John

Name and version of the database you are using:
MySQL 5.0

Mapping documents:


Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.portal.model">

   <class name="User" table="TBL_USER">
      <id name="id" type="integer" column="USER_ID">
         <generator class="native" />
      </id>
      
      <property name="externalCommonId" type="string"
         column="EXTERNAL_COMM_ID" length="30" unique="true"
         index="TBL_USER_external_common_id" />
      <property name="login" type="string" column="LOGIN" length="30"
         unique="true" index="TBL_USER_login" />
      <property name="password" type="string" column="PASSWORD"
         length="30" />

      <property name="firstName" type="string" column="FIRST_NAME"
         length="25" />
      <property name="lastName" type="string" column="LAST_NAME"
         length="30" />
      <property name="title" type="string" column="TITLE"
         length="100" />
      <property name="phoneNumber" type="string" column="WRK_TEL_NUM"
         length="25" />
      <property name="email" type="string" column="EMAIL"
         length="100" />
      <property column="USR_CREATED_DT" name="createdDate"
         type="timestamp" generated="insert" />
      <property name="active" type="true_false" column="ACTIVE" />
   </class>

</hibernate-mapping>



Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.portal.model">
<class name="JoinUserToUserGroup"
     table="TBL_JOIN_USERGRP_TO_USER">
   
    <id
        name="id"
        type="integer"
        column="JID"
    >
        <generator class="native" />
    </id>
    <property
        name="userGroupId"
        type="integer"
        column="USER_GROUP_ID"
        index="TBL_JOIN_USERGRP_TO_USER_usergroupID"
    />
    <property
        name="userId"
        type="integer"
        column="USER_ID"
        index="TBL_JOIN_USERGRP_TO_USER_userID"
    />
</class>
</hibernate-mapping>


Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.portal.model">

        <class name="UserGroup"
            table="TBL_USER_GROUP">   
            <id
              name="id"
             type="integer"
             column="USER_GROUP_ID"
         >
              <generator class="native" />
            </id>
            <property
                 name="userGrpCd"
                 type="java.lang.String"
                 column="GRP_CD"
                 length="15"
             />
             <property
                 name="userGrpDesc"
                 type="java.lang.String"
                 column="GRP_DESC"
                 length="40"
             />
             <property
                 name="sysAcct"
                 type="true_false"
                 column="SYS_ACCT"
                 length="3"
             />
             <property
             name="active"
             type="true_false"
             column="ACTIVE"
             />
        </class>
       
</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 23, 2006 3:24 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
1) create a variable in your User class
called usergroups
ie.
Set usergroups=null;
provide get and set methods
public void setUsergroups(Set s){}
public Set getUsergroups(){return usergroups;}
- the capital U in get/set is crucial and according to the bean spec.

2) create a variable in your UserGroups class
called users
ie.
Set users=null;
do get and set methods.

3) modify User.hbm.xml to add:
<set name="usergroups" table="Join_Users_to_Usergroup" lazy="false" cascade="all" inverse="true">
<key column="user_id"/>
<many-to-many class="UserGroups" column="usergroup_id" outer-join="true"/>
</set>


4) modify the UserGroups.hbm.xml

<set name="users" table="Join_Users_to_Usergroup"
lazy="false" cascade="none" >
<key column="usergroup_id"/>
<many-to-many class="User" column="user_id" outer-join="auto"/>
</set>

5) get rid of the Join_Users_to_Usergroup mapping and class that you have - not needed.

That should get you going...

_________________
-JT

If you find my replies helpful, please rate by clicking 'Y' on them. I appreciate it.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 24, 2006 3:09 pm 
Newbie

Joined: Sun Sep 18, 2005 6:34 pm
Posts: 12
Ran into one issue...
I updated my hbm.xml's and told hibernate to drop and recreate all POJOS and DB. I then retested... My Join table which holds the relationship between user and usergroups was not getting populated with values.... However,my classes did return the relationships when durring runtime but never saw those valuse appear in the DB

I tinkered around with the HBM.XML's and changed the following

removed ... inverse="true" and set outer-join="auto" from "true" and then regenerated everything... I could then see the values in my database join table.

What is INVERSE used for? I read the hibernate help doc , but didnt get what they were saying or why the removal would effect persisting data to the DB? If you could shed some light it please do :)

PS.. Thanks for your help... and also....The link to click so you can get you credit point for helping me is no where to be found!!!!! Maybe after this response it will somehow be enabled or magically appear.... lets see if "Y" appears


Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.portal.model">

   <class name="User" table="TBL_USER">
      <id name="id" type="integer" column="USER_ID">
         <generator class="native" />
      </id>
      <!-- Keep old set copy -->
      <!-- set name="Usergroups" table="TBL_JOIN_USER_TO_USERGROUP" lazy="false" cascade="all" inverse="true">
         <key column="user_id"/>
         <many-to-many class="UserGroup" column="USER_GROUP_ID" outer-join="true"/>
      </set-->
      <set name="Usergroups" table="TBL_JOIN_USER_TO_USERGROUP" lazy="false" cascade="all" >
         <key column="USER_ID"/>
         <many-to-many class="UserGroup" column="USER_GROUP_ID" outer-join="auto"/>
      </set>

      <property name="externalCommonId" type="string"
         column="EXTERNAL_COMM_ID" length="30" unique="true"
         index="TBL_USER_external_common_id" />
      <property name="login" type="string" column="LOGIN" length="30"
         unique="true" index="TBL_USER_login" />
      <property name="password" type="string" column="PASSWORD"
         length="30" />

      <property name="firstName" type="string" column="FIRST_NAME"
         length="25" />
      <property name="lastName" type="string" column="LAST_NAME"
         length="30" />
      <property name="title" type="string" column="TITLE"
         length="100" />
      <property name="phoneNumber" type="string" column="WRK_TEL_NUM"
         length="25" />
      <property name="email" type="string" column="EMAIL"
         length="100" />
      <property column="USR_CREATED_DT" name="createdDate"
         type="timestamp" generated="insert" />
      <property name="active" type="true_false" column="ACTIVE" />
   </class>

</hibernate-mapping>



Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.portal.model">

        <class name="UserGroup"
            table="TBL_USER_GROUP">   
            <id
              name="id"
             type="integer"
             column="USER_GROUP_ID"
         >
              <generator class="native" />
            </id>

<!-- Keep old set copy -->         
<!-- set name="Users" table="TBL_JOIN_USER_TO_USERGROUP"
         lazy="false" cascade="none" >
            <key column="USER_GROUP_ID"/>
            <many-to-many class="User" column="user_id" outer-join="auto"/>
         </set-->
         <set name="Users" table="TBL_JOIN_USER_TO_USERGROUP" lazy="false" cascade="all">
            <key column="USER_GROUP_ID"/>
            <many-to-many class="User" column="USER_ID" outer-join="auto"/>
         </set>
            <property
                 name="userGrpCd"
                 type="java.lang.String"
                 column="GRP_CD"
                 length="15"
             />
             <property
                 name="userGrpDesc"
                 type="java.lang.String"
                 column="GRP_DESC"
                 length="40"
             />
             <property
                 name="sysAcct"
                 type="true_false"
                 column="SYS_ACCT"
                 length="3"
             />
             <property
             name="active"
             type="true_false"
             column="ACTIVE"
             />
        </class>
       
</hibernate-mapping>


Top
 Profile  
 
 Post subject: inverse guidelines...
PostPosted: Fri Feb 24, 2006 4:30 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
I admit the "inverse" concept is a bit allusive - generally speaking I end up
using the following guidelines, and then testing to make sure it is saving the way I want:

For bi-directional relationships, 1-M and M-M make sure you put the inverse attribute in the collection tag. For M-M it doesn't matter, but for 1-M it goes in the only collection tag involved in this relationship.

Inverse tells hibernate which end of the relationship to get information about the link... so if you put inverse="true" on your ONE side ie.
<class name="parent"> <!-- this is the ONE side -->
<set name="children" ...inverse="true">
</set>
Then you are telling hibernate that the "many" side ie, Child class is managing the "link" info (in a bi-directional association). In a non-bidirectional one-to-many, ie the parent just has many children, and the child object doesn't know about the parent - Hibernate just defaults to the right management, ie managed by the parent.

I hope this makes sense, and please, someone correct me if I am wrong or misleading with this.

Here is a quote from the docs:

section 1.3.6. Working bi-directional links in reference.pdf

Quote:
All bi-directional associations need one side as inverse. In a one-to-many association it has to be the many-side, in many-to-many association you can pick either side, there is no difference.


Sounds like your code is working. right???

_________________
-JT

If you find my replies helpful, please rate by clicking 'Y' on them. I appreciate it.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 24, 2006 5:29 pm 
Newbie

Joined: Sun Sep 18, 2005 6:34 pm
Posts: 12
Yes I do have it working, and TY for your help!


Top
 Profile  
 
 Post subject: Ok spoke too soon, 75% is working :)
PostPosted: Fri Feb 24, 2006 6:26 pm 
Newbie

Joined: Sun Sep 18, 2005 6:34 pm
Posts: 12
Ok spoke too soon, 75% is working :)

Heres what Ive got so far ....

(This works 100%)
adding Usergroups to User via User.setUsergroups() works; (Values appear in the DB correctly) and can be retived and displayed via User.getUsergroups();

(This works 50%)
adding Users to Usergroups via Usergroup.setUsers() works ---I think---; (Values appear in the DB join table correctly!) but these users cannot be retived and displayed via UserGroup.getUsers()--- (set returned is empty)

Is this still a mapping issue ???


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 24, 2006 6:53 pm 
Expert
Expert

Joined: Mon Jan 09, 2006 5:01 pm
Posts: 311
Location: Sacramento, CA
just a thought here, but check to make sure (in your java code) you are setting the bi-directional references... in other words, when you create a user, and usergroup make sure they both are added to each other via their "set" methods. Also verify the keys are populated correctly in the db.

_________________
-JT

If you find my replies helpful, please rate by clicking 'Y' on them. I appreciate it.


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:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.