-->
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.  [ 10 posts ] 
Author Message
 Post subject: Schema export: relation table created without primary key
PostPosted: Wed Feb 01, 2006 6:38 am 
Newbie

Joined: Wed Feb 01, 2006 6:17 am
Posts: 11
Hibernate version: 1.0.2
Name and version of the database you are using: SQL Server 2000

When I create the DB using SchemaExport 3 tables are generated:
tUser (with ID PK), tOrder (with ID PK) and rOrderToUser (relation table between order and user). However the relation table rOrderToUser is created without the desired PK (UserID + OrderID).
I guess my mapping is incorrect, and I should use <composite-id>, but I couldn't figure out the right way of doing it. Any help would be appreciated.
Ruby


User Mapping File:
Code:
  <class name="TestNameSpace.User, impl" table="tUser">
    <id name="Id" type="Int32" column="ID">
      <generator class="assigned" />
    </id>
    <property name="Name" column="Name" type="String" />
    <bag name="Orders" table="rOrderToUser">
      <key column="UserID" />
      <many-to-many column="OrderID" class="TestNameSpace.Order, impl" />
    </bag>
  </class>



Order Mapping File:
Code:
  <class name="TestNameSpace.Order, impl" table="tOrder">
    <id name="Id" type="Int32" column="ID">
      <generator class="assigned" />
    </id>
    <property name="Price" column="Price" type="String" />
    <bag name="Users" table="rOrderToUser" inverse="true">
      <key column="OrderID" />
      <many-to-many column="UserID" class="TestNameSpace.User, impl" />
    </bag>
  </class>


Top
 Profile  
 
 Post subject: Re: Schema export: relation table created without primary ke
PostPosted: Wed Feb 01, 2006 7:03 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
ruby wrote:
When I create the DB using SchemaExport 3 tables are generated:
tUser (with ID PK), tOrder (with ID PK) and rOrderToUser (relation table between order and user). However the relation table rOrderToUser is created without the desired PK (UserID + OrderID).
I guess my mapping is incorrect, and I should use <composite-id>, but I couldn't figure out the right way of doing it. Any help would be appreciated.

Code:
  <bag name="Orders" table="rOrderToUser">
      <key column="UserID" />
      <many-to-many column="OrderID" class="TestNameSpace.Order, impl" />
    </bag>

AFAIK, the bag can contain one element multiple times so the generated schema is correct. The set has "element-only-once" semantic...

Gert


Top
 Profile  
 
 Post subject: Schema export: relation table without primary key (Solved)
PostPosted: Wed Feb 01, 2006 1:53 pm 
Newbie

Joined: Wed Feb 01, 2006 6:17 am
Posts: 11
Gert, Thank you very much.
Using <set> instead of <bag> did the trick.
Ruby


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 01, 2006 3:54 pm 
Newbie

Joined: Wed Feb 01, 2006 6:17 am
Posts: 11
Hi again,
A new problem came up:
after using <set> instead of <bag> I can't save an order:

Code:
Code:
Order order = new Order();
order.Price = 100.0;
ISession session = sessionFactory.OpenSession();
session.Save(order);
session.Close();


Exception:
Quote:
Could not save object
Specified cast is not valid.
at NHibernate.Type.SetType.Wrap(ISessionImplementor session, Object collection)
at NHibernate.Impl.WrapVisitor.ProcessArrayOrNewCollection(Object collection, PersistentCollectionType collectionType)
at NHibernate.Impl.WrapVisitor.ProcessCollection(Object collection, PersistentCollectionType collectionType)
at NHibernate.Impl.AbstractVisitor.ProcessValue(Object value, IType type)
at NHibernate.Impl.WrapVisitor.ProcessValues(Object[] values, IType[] types)
at NHibernate.Impl.SessionImpl.DoSave(Object theObj, Key key, IClassPersister persister, Boolean replicate, Boolean useIdentityColumn, CascadingAction cascadeAction, Object anything)
at NHibernate.Impl.SessionImpl.DoSave(Object obj, Object id, IClassPersister persister, Boolean useIdentityColumn, CascadingAction cascadeAction, Object anything)
at NHibernate.Impl.SessionImpl.SaveWithGeneratedIdentifier(Object obj, CascadingAction action, Object anything)



Using <bag> instead of <set> in order mapping (see below) works fine but when creating the DB using SchemaExport, the relation table rOrderToUser is created without the desired PK (UserID + OrderID).
Any ideas regarding the cast exception?
Ruby

Order Mapping:
Code:
  <class name="TestNameSpace.Order, impl" table="tOrder">
    <id name="Id" type="Int32" column="ID">
      <generator class="assigned" />
    </id>
    <property name="Price" column="Price" type="Double" />
    <set name="Users" table="rOrderToUser" inverse="false">
      <key column="OrderID" />
      <many-to-many column="UserID" class="TestNameSpace.User, impl" />
    </set>
  </class>


User Mapping:
Code:
  <class name="TestNameSpace.User, impl" table="tUser">
    <id name="Id" type="Int32" column="ID">
      <generator class="assigned" />
    </id>
    <property name="Name" column="Name" type="String" />
  </class>
[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 01, 2006 4:54 pm 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
ruby wrote:
Hi again,
A new problem came up:
after using <set> instead of <bag> I can't save an order:


What is the type of property? For <set>, it should be Iesi.Collections.ISet or System.Collections.ICollection

Gert


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 01, 2006 7:05 pm 
Newbie

Joined: Wed Feb 01, 2006 6:17 am
Posts: 11
It is of type ArrayList (System.Collections.ICollection):

Code:
namespace TestNameSpace
{
   public class Order
   {
      private Int32 id;
      private Double price;
      private IList users = new ArrayList();

      public Int32 Id
      {
         get { return id; }
         set { id = value; }
      }

      public double Price
      {
         get { return price; }
         set { price = value; }
      }

      public IList Users
      {
         get { return users; }
         set { users = value; }
      }
   }
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 02, 2006 1:55 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
ruby wrote:
It is of type ArrayList (System.Collections.ICollection):

Code:
      private IList users = new ArrayList();
      public IList Users
      {
         get { return users; }
         set { users = value; }
      }


Well, currection: You have its type of IList. Try to chnage it
public ICollection Users {get; set; }
or event better
public ISet Users {get; set; }

You should also use Iesi.Collections.HashedSet as class: When restoring set from datavase the NHibernmate will create an class equivalent to that.

Gert


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 02, 2006 3:26 am 
Newbie

Joined: Wed Feb 01, 2006 6:17 am
Posts: 11
These declerations cause the exception:
Code:
private ICollection users = new ArrayList();
public ICollection Users
      {
         get { return users; }
         set { users = value; }
      }


private IList users = new ArrayList();
public IList Users
      {
         get { return users; }
         set { users = value; }
      }



These declerations work fine:
Code:
private ISet users = new ListSet();
public ISet Users
      {
         get { return users; }
         set { users = value; }
      }


private ISet users = new HashedSet();
public ISet Users
      {
         get { return users; }
         set { users = value; }
      }



So when using <set> I can't use ICollection instances (i.e. ArrayList) and must use ISet objects (i.e. ListSet) . But when using <bag> I can use ICollection instances. This behaviour is quite problematic as I see it. Any thoughts?
Ruby


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 02, 2006 3:33 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
ruby wrote:
So when using <set> I can't use ICollection instances (i.e. ArrayList) and must use ISet objects (i.e. ListSet) . But when using <bag> I can use ICollection instances. This behaviour is quite problematic as I see it. Any thoughts?


You could try one more combination:
Code:
private ICollection users = new HashedSet();
public ICollection Users
      {
         get { return users; }
         set { users = value; }
      }



Anyway, if You require element-once-in-collection behaviour then it is better to use Set instance - so You can not add an element twice to collection accidentially.

Gert


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 02, 2006 4:23 am 
Newbie

Joined: Wed Feb 01, 2006 6:17 am
Posts: 11
Thanks Gert, it works now.

So the solution is:

User mapping:
Code:
  <class name="TestNameSpace.User, impl" table="tUser">
    <id name="Id" type="Int32" column="ID">
      <generator class="native" />
    </id>
    <property name="Name" column="Name" type="String" />
  </class>


Order mapping:
Code:
<class name="TestNameSpace.Order, impl" table="tOrder">
    <id name="Id" type="Int32" column="ID">
      <generator class="native" />
    </id>
    <property name="Price" column="Price" type="Double" />
    <set name="Users" table="rOrderToUser" cascade="all" inverse="false">
      <key column="OrderID" />
      <many-to-many column="UserID" class="TestNameSpace.User, impl" />
    </set>
  </class>


User class:
Code:
namespace TestNameSpace
{
   public class User
   {
      private Int32 id;
      private String name;

      public Int32 Id
      {
         get { return id; }
         set { id = value; }
      }

      public String Name
      {
         get { return name; }
         set { name = value; }
      }
   }
}

Order Class:
Code:
namespace TestNameSpace
{
   public class Order
   {
      private Int32 id;
      private Double price;
      private ICollection users = new HashedSet();

      public Int32 Id
      {
         get { return id; }
         set { id = value; }
      }

      public double Price
      {
         get { return price; }
         set { price = value; }
      }

      public ICollection Users
      {
         get { return users; }
         set { users = value; }
      }
   }
}


Test Flow:
Code:
Order order = new Order();
order.Price = 100.0;
User user = new User();
user.Name = "MyName";
((HashedSet)order.Users).Add(user);
ISession session = sessionFactory.OpenSession();
ITransaction transaction = session.BeginTransaction();
session.Save(order);
transaction.Commit();
session.Close();


DB created with all desiered PKs and data saved to all tables in DB.
Thanks again
Ruby.


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