-->
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.  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: How do I map this?
PostPosted: Sun Nov 23, 2003 9:38 pm 
Regular
Regular

Joined: Thu Nov 20, 2003 10:04 pm
Posts: 64
Location: Melbourne, Australia
Say I have the following tables:

Code:
TableUser
    UserId
    UserName
TableGroup
    GroupId
    GroupName
TableUserGroup
    UserId
    GroupId
    StartDate
    EndDate


Now if TableUserGroup didn't have the start and end date stuff it would be simple enough to map TableUser and TableGroup together in a many-to-many association but I'm not sure what the best way to map these is when the table serving as the many-to-many has this "extra" information associated with it.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Nov 23, 2003 9:55 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
Use <composite-element>

http://www.hibernate.org/hib_docs/refer ... nents-s2-2


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 7:20 pm 
Regular
Regular

Joined: Thu Nov 20, 2003 10:04 pm
Posts: 64
Location: Melbourne, Australia
The composite-element doesn't seemed to be allowed in combination with a many-to-many mapping. Anyone got a quick example?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 7:29 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
Hey, have you read documentation carefully?

"A special case of a composite element is a composite element with a nested <many-to-one> element. A mapping like this allows you to map extra columns of a many-to-many association table to the composite element class. The following is a many-to-many association from Order to Item where purchaseDate, price and quantity are properties of the association: "

Code:
<class name="eg.Order" .... >
    ....
    <set name="purchasedItems" table="purchase_items" lazy="true">
        <key column="order_id">
        <composite-element class="eg.Purchase">
            <property name="purchaseDate"/>
            <property name="price"/>
            <property name="quantity"/>
            <many-to-one name="item" class="eg.Item"/> <!-- class attribute is optional -->
        </composite-element>
    </set>
</class>


Am I wrong or is this EXACTLY what you need?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 7:39 pm 
Regular
Regular

Joined: Thu Nov 20, 2003 10:04 pm
Posts: 64
Location: Melbourne, Australia
Arghhh... sorry. I'm not feeling to well at the moment and my brain is clogged. That's exactly it. Many thanks.


Top
 Profile  
 
 Post subject: Composite-element properties in queries
PostPosted: Mon Nov 24, 2003 7:53 pm 
Regular
Regular

Joined: Thu Nov 20, 2003 10:04 pm
Posts: 64
Location: Melbourne, Australia
Just reading a bit further it appears that composite-element properties can't be used in queries. This might become a problem for me. For the moment I think I can live with it.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 9:39 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Composite elements may be used in queried in Hibernate 2.1.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 9:48 pm 
Regular
Regular

Joined: Thu Nov 20, 2003 10:04 pm
Posts: 64
Location: Melbourne, Australia
gavin wrote:
Composite elements may be used in queried in Hibernate 2.1.


Excellent. You may want to update section 6.2 (at the bottom) to remove the warning that you can't.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 9:52 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
If you are reading documentation on the site, you should know, it is for 2.0


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 24, 2003 10:21 pm 
Regular
Regular

Joined: Thu Nov 20, 2003 10:04 pm
Posts: 64
Location: Melbourne, Australia
dimas wrote:
If you are reading documentation on the site, you should know, it is for 2.0


Looking in the local docs it appears to be okay.


Top
 Profile  
 
 Post subject: One other thing
PostPosted: Tue Nov 25, 2003 1:08 am 
Regular
Regular

Joined: Thu Nov 20, 2003 10:04 pm
Posts: 64
Location: Melbourne, Australia
When I use this mechanism to create the many-to-many relationship the table sql that is generated looks like this:

Code:
create table usergroups (
   UserId VARCHAR(20) not null,
   UserJoinDate DATETIME,
   UserEndDate DATETIME,
   GroupId INTEGER not null
);


Notice there's no primary key defined. Is there anyway to specify that UserId and GroupId should be a primary key?

Also if I want to make the relationship two way do I just define the same sort of relationship on the group mapping file?


Top
 Profile  
 
 Post subject: Re: One other thing
PostPosted: Tue Nov 25, 2003 2:07 am 
Regular
Regular

Joined: Thu Nov 20, 2003 10:04 pm
Posts: 64
Location: Melbourne, Australia
gstamp wrote:
When I use this mechanism to create the many-to-many relationship the table sql that is generated looks like this:

Code:
create table usergroups (
   UserId VARCHAR(20) not null,
   UserJoinDate DATETIME,
   UserEndDate DATETIME,
   GroupId INTEGER not null
);


Notice there's no primary key defined. Is there anyway to specify that UserId and GroupId should be a primary key?

Also if I want to make the relationship two way do I just define the same sort of relationship on the group mapping file?


Actually it's worse than this. When I try and update an existing usergroup hibernate adds a duplicate row.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 25, 2003 3:05 am 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
Hm...
Could you try to use <map> instead of <set>? I believe <map> should automatically enforce PK.

Not sure about two-way. Probably, it will work but I wouldn't do that - this becomes ambigous because you will have two sets (set of Groups for User and set of Users for group). I think it is almost impossible for Hibernate to track changes made to these sets because they can conflict.

And about duplicates: hard to guess without you mappings/sources. Have you read FAQ? Is everything Ok with <id>, unsaved-value, equals() etc?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 25, 2003 3:58 am 
Regular
Regular

Joined: Thu Nov 20, 2003 10:04 pm
Posts: 64
Location: Melbourne, Australia
dimas wrote:
Hm...
Could you try to use <map> instead of <set>? I believe <map> should automatically enforce PK.

Not sure about two-way. Probably, it will work but I wouldn't do that - this becomes ambigous because you will have two sets (set of Groups for User and set of Users for group). I think it is almost impossible for Hibernate to track changes made to these sets because they can conflict.

And about duplicates: hard to guess without you mappings/sources. Have you read FAQ? Is everything Ok with <id>, unsaved-value, equals() etc?


Here's the user mapping (with a number of non-relevant bits deleted):

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

<class
    name="com.avalon.seaview.domain.User"
    table="seaviewuser"
>
    <!-- <cache usage="read-only"/> -->
    <id name="userId" type="java.lang.String" column="UserId" length="20">
        <generator class="assigned"/>
    </id>

    <set name="userGroups" lazy="true" table="usergroups">
        <key column="UserId" />
        <composite-element class="com.avalon.seaview.domain.UserGroup">
            <property name="userJoinDate" column="UserJoinDate" type="java.util.Date" />
            <property name="userEndDate" column="UserEndDate" type="java.util.Date"/>
            <many-to-one name="group" class="com.avalon.seaview.domain.Group" column="GroupId" not-null="true"/>
        </composite-element>
    </set>

</class>
</hibernate-mapping>


This is the user class (again with bits deleted):

Code:
public class User implements Serializable
{
    private String userId;
    private Set userGroups;

    public String getUserId()
    {
        return this.userId;
    }

    public void setUserId( String userId )
    {
        this.userId = userId;
    }

    public Set getUserGroups()
    {
        return this.userGroups;
    }

    public void setUserGroups( Set userGroups )
    {
        this.userGroups = userGroups;
    }

    public boolean equals( Object other )
    {
        if ( !( other instanceof User ) ) return false;
        User castOther = (User) other;
        return new EqualsBuilder()
                .append( this.getUserId(), castOther.getUserId() )
                .isEquals();
    }

    public int hashCode()
    {
        return new HashCodeBuilder()
                .append( getUserId() )
                .toHashCode();
    }

}


UserGroup table:

Code:
public class UserGroup implements Serializable
{

    private Date userJoinDate;
    private Date userEndDate;
    private Group group;

    public UserGroup()
    {
    }

    public Date getUserJoinDate()
    {
        return this.userJoinDate;
    }

    public void setUserJoinDate( Date userJoinDate )
    {
        this.userJoinDate = userJoinDate;
    }

    public Date getUserEndDate()
    {
        return this.userEndDate;
    }

    public void setUserEndDate( Date userEndDate )
    {
        this.userEndDate = userEndDate;
    }

    public Group getGroup()
    {
        return group;
    }

    public void setGroup( Group group )
    {
        this.group = group;
    }

    public boolean equals( Object o )
    {
        if ( this == o ) return true;
        if ( !( o instanceof UserGroup ) ) return false;

        final UserGroup userGroup = (UserGroup) o;

        if ( group != null ? !group.equals( userGroup.group ) : userGroup.group != null ) return false;

        return true;
    }

    public int hashCode()
    {
        return ( group != null ? group.hashCode() : 0 );
    }

    public String toString()
    {
        return "com.avalon.seaview.domain.UserGroup{" +
                "userJoinDate=" + userJoinDate +
                ", userEndDate=" + userEndDate +
                "}";
    }

}


One iffy thing I can think of might be to do with the userGroup equals and hashcode implementations. The couldn't fine a reference in the manual for what to do with composite equals() and hashcode(). I tried including all the fields but the result was the same.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 25, 2003 8:38 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
(1) a primary key may only contain not-null columns, so set them not-null="true"

(2) I'm quite sure you are getting duplicate rows because of the equals()/hashCode() implementation. Remember: if you change the hashCode of an object while it is in a set, you break the Set contract! So when you update the object, you are probably changing the hashCode.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 18 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.