-->
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.  [ 6 posts ] 
Author Message
 Post subject: Composite key mapping
PostPosted: Tue May 30, 2006 12:10 pm 
Newbie

Joined: Tue May 30, 2006 11:54 am
Posts: 6
Hibernate version: 1.0.2

Name and version of the database you are using: MS SQL 2000

I have following structure (simplified):

User table
Role table
UserRole table

User table:
userid (PK), username

Role table:
roleid (PK), rolename

UserRole table:
userid (PK, FK to User), roleid (PK, FK to user)

What mapping must be?
In the UserRole.hbm.xml I write

Code:
<composite-id>
    <key-property name="Userid" column="userid" />
    <key-property name="Roleid" column="roleid" />
</composite-id>

<many-to-one name="RolesByRoleid" column="roleid" class="Sly.Csrs.Data.RolesEntity, DAO" insert="false" update="false" not-null="true" />
<many-to-one name="UsersByUserid" column="userid" class="Sly.Csrs.Data.UsersEntity, DAO" insert="false" update="false" not-null="true" />


But when I assigns User and Role objects (through RolesByRolwid and UserByUserid properties) and then tries to save UserRole I get exception.
I saw to SQL generated for saving. First thing NHibernate does ir tries to select existing UserRole (thinking userid=0, roleid=0). Of cause, it doesn't exist.
Then it tries to execute the following
INSERT INTO UserRole (userid, roleid) VALUES (0, 0)
And, of cause , obtains an error because there areno role and user with such ids.
Why doesn't it get identifiers from the related objects?
What must I do ? May be another approach?
I couldn't change DB.

Pleease, help me.
Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 30, 2006 2:13 pm 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
did you persist (save) the User and Role object before you tried to create a UserRole object? Since cascade defaults to none NH would not persist the User or Role entity through the UserRole entity...

-devon


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 31, 2006 11:00 am 
Newbie

Joined: Tue May 30, 2006 11:54 am
Posts: 6
devonl wrote:
did you persist (save) the User and Role object before you tried to create a UserRole object? Since cascade defaults to none NH would not persist the User or Role entity through the UserRole entity...

-devon


Yes, I save User object before creating UserRole object, after that I assigned UsersByUserid property with this saved object but this doesn't solve my problem.

Furthemore, I want to cascade saving objects (when I save UserRole - User and Role objects saved previously), but when I delete "update=false" and "insert=false" attributes from the declsration then mapping error occurs.

What do I do wrong?


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 31, 2006 1:49 pm 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
you've got something else going wrong there. can you please post the class definitions and mapping files for User and Role and UserRole. also, include a snippet code where you are attempting to create User and UserRole associations. thanks,

-devon


Top
 Profile  
 
 Post subject: Sources
PostPosted: Wed May 31, 2006 2:29 pm 
Newbie

Joined: Tue May 30, 2006 11:54 am
Posts: 6
UsersEntityBase.cs

Code:
public class UsersEntityBase : BaseEntity {
   
    private System.String _Fname = "";
    public System.String Fname {
        get { return this._Fname; }
        set { this._Fname = value; }
    }   
    private System.Int32 _Userid = 0;
    public System.Int32 Userid {
        get { return this._Userid; }
        set  { this._Userid = value; }
    }   
       
    public UsersEntityBase (System.Int32 _Userid)
    { this._Userid = _Userid; }
               
    private IList m_UserRoleEntities = null;
    public IList UserRoleEntities
    {
        get
        {
                IList collection = (IList) InitializeProperty (m_UserRoleEntities);
                if (collection == null) {
                    collection = new ArrayList();
                    this.m_UserRoleEntities = collection;
                }
                return collection;
        }
        set { m_UserRoleEntities = value; }
    }
}


RolesEntityBase class is similar (replace "User" By "Role")

UserRoleEntityBase.cs

Code:
public class UserRoleEntityBase : BaseEntity {
          
    private System.Int32 _Roleid = 0;
    public System.Int32 Roleid {
        get { return this._Roleid; }
        set { this._Roleid = value; }
    }   
    private System.Int32 _Userid = 0;
    public System.Int32 Userid {
        get  { return this._Userid; }
        set  { this._Userid = value; }
    }   
    /// <summary>
    /// Default constructor.
    /// </summary>
    public UserRoleEntityBase ()
    {}
       
    public UserRoleEntityBase (System.Int32 _Userid, System.Int32 _Roleid )
    {
        this._Userid = _Userid;
        this._Roleid = _Roleid;
    }
               
    private RolesEntity RolesBy_Roleid = null;
    public RolesEntity RolesByRoleid {
        get { return this.RolesBy_Roleid ; }
        set { this.RolesBy_Roleid = value; }
    }
    private UsersEntity UsersBy_Userid = null;
    public UsersEntity UsersByUserid {
        get { return this.UsersBy_Userid ; }
        set { this.UsersBy_Userid = value; }
    }
      
}


Mapping Files:
Users.hbm.xml

Code:
<?xml version="1.0" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    <class name="Sly.Csrs.Data.UsersEntity, DAO" table="Users">
        <id name="Userid" column="userid">
            <generator class="identity"/>
        </id>
        <bag name="UserRoleEntities" inverse="true" lazy="true" cascade="all" >
            <key column="userid" />
            <one-to-many class="Sly.Csrs.Data.UserRoleEntity, DAO" />
        </bag>
        <property name="Fname" column="fname" not-null="true" />
    </class>
</hibernate-mapping>


Roles.hbm.xml is almost identical.

UserRole.hbm.xml

Code:
<?xml version="1.0" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    <class name="Sly.Csrs.Data.UserRoleEntity, DAO" table="UserRole">
        <composite-id>
            <key-property name="Userid" column="userid" />
            <key-property name="Roleid" column="roleid" />
        </composite-id>
        <many-to-one name="RolesByRoleid" column="roleid" class="Sly.Csrs.Data.RolesEntity, DAO" insert="false" update="false" not-null="true" />
        <many-to-one name="UsersByUserid" column="userid" class="Sly.Csrs.Data.UsersEntity, DAO" insert="false" update="false" not-null="true" />
    </class>
</hibernate-mapping>


Sample code

Code:
UsersEntity user = new UsersEntity ();
user.FName = Guid.NewGuid().ToString();
using (ISession session = factory.OpenSession())
{
    session.SaveOrUpdateCopy(user);
    session.Flush();
}

UserRoleEntity userRole = new UserRoleEntity ();     
userRole.RolesByRoleid = new RolesEntity ();
userRole.UsersByUserid = user;
user.UserRoleEntities.Add(userRole);
using (ISession session = factory.OpenSession())
{
    // Error occured on the line below
    session.SaveOrUpdateCopy(userRole);
    session.Flush();
}


When I look to the db profiler I see that NHibernate tries to select using following query (before this it checks that such row doesn't exist yet):
Code:
INSERT INTO UserRole (userid, roleid) VALUES (0, 0)


What is wrong?

Thanks!


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 31, 2006 2:47 pm 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
well, if i'm reading your code right, you are creating a new transient UserEntity and then calling SaveOrUpdateCopy(). Most likely NH is choking on the use of SaveOrUpdateCopy() because it doesn't know how to tell the entity is transient. you should try to increaase the granularity of all of your mapping files to at least include "unsaved-value" attribute for all ID fields. IMHO, you should also set up <version> attributes, or <timestamp> attributes to "help" NH understand the state of its persistence. you need to be sure your constructors are setting the unsaved value to match the mapping files. (also, IDs, when determined by the database should be immutable IMHO so no setter for UserID.) check your log files and i think you'll see what NH is doing when it tries to save the object.

in a nutshell:
Code:
<?xml version="1.0" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    <class name="Sly.Csrs.Data.UsersEntity, DAO" table="Users">
        <id name="Userid" column="userid" unsaved-value="0" access="field">
            <generator class="identity"/>
        </id>
        <bag name="UserRoleEntities" inverse="true" lazy="true" cascade="all-delete-orphan" >
            <key column="userid" />
            <one-to-many class="Sly.Csrs.Data.UserRoleEntity, DAO" />
        </bag>
        <property name="Fname" column="fname" not-null="true" />
    </class>
</hibernate-mapping>


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