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.  [ 4 posts ] 
Author Message
 Post subject: one-to-many and many-to-one Childmapping needs parentobject?
PostPosted: Fri Dec 08, 2006 11:07 am 
Beginner
Beginner

Joined: Thu Oct 26, 2006 4:45 am
Posts: 39
Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version: 1.0.2

Mapping documents:

relevant parts are:

parent:
Code:
    <bag name="BookedRoomsUntyped" table="RoomBooking" lazy="false" cascade="all">
      <key column="HotelBookingId"/>
      <one-to-many class="Airtrade.Business.Hotels.RoomBooking, Airtrade.Business.Hotels"/>
   </bag>


and child:
Code:
      <many-to-one name="HotelBookingId" class="Airtrade.Business.Hotels.HotelBooking,  Airtrade.Business.Hotels" column="HotelBookingId"  />


also, it is important that in the Roombooking-mapping file there is a collection of persons.

Full stack trace of any exception that occurs:
Name and version of the database you are using: Sql server 2005

The generated SQL (show_sql=true):
See above at stacktrace: the thing is that the RoomBooking record is not saved to the database.

Debug level Hibernate log excerpt:
Code:
2006-12-08 15:58:02,921 [TestRunnerThread] DEBUG NHibernate.Impl.BatcherImpl - Opened Reader, open Readers :1
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Persister.AbstractEntityPersister - Natively generated identity: 2581
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Driver.NHybridDataReader - running NHybridDataReader.Dispose()
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Impl.BatcherImpl - Closed Reader, open Readers :0
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Impl.BatcherImpl - Closed IDbCommand, open IDbCommands :0
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Engine.Cascades - processing cascades for: Airtrade.Business.Hotels.HotelBooking
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Engine.Cascades - cascading to collection: Airtrade.Business.Hotels.HotelBooking.BookedRoomsUntyped
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Engine.Cascades - cascading to SaveOrUpdate()
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Engine.Cascades - unsaved-value: 0
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Impl.SessionImpl - SaveOrUpdate() unsaved instance
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Impl.SessionImpl - saving [Airtrade.Business.Hotels.RoomBooking#<null>]
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Impl.SessionImpl - executing insertions
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Engine.Cascades - processing cascades for: Airtrade.Business.Hotels.RoomBooking
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Engine.Cascades - done processing cascades for: Airtrade.Business.Hotels.RoomBooking
2006-12-08 15:58:02,937 [TestRunnerThread] DEBUG NHibernate.Impl.WrapVisitor - Wrapped collection in role: Airtrade.Business.Hotels.RoomBooking.MappedGuests
2006-12-08 15:58:02,968 [TestRunnerThread] DEBUG NHibernate.Util.ADOExceptionReporter - Could not save object
System.ArgumentException: There is a problem with your mappings.  You are probably trying to map a System.ValueType to a <class> which NHibernate does not allow or you are incorrectly using the IDictionary that is mapped to a <set>. 

A ValueType can not be used with IdentityKey.  The thread at google has a good description about what happens with boxing and unboxing ValueTypes and why they can not be used as an IdentityKey: http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&threadm=bds2rm%24ruc%241%40charly.heeg.de&rnum=1&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DUTF-8%26oe%3DUTF-8%26q%3DSystem.Runtime.CompilerServices.RuntimeHelpers.GetHashCode%26sa%3DN%26tab%3Dwg
Parameter name: key


How come the Roombooking (child of HotelBooking) is not saved correctly to the database? What is wrong with my roombooking mapping?

I did get the parent-child relation to work when I also use the parent-object as a property in the child-object (instead of only the parent-KEYFIELD)
and then I had to use the following in the mappingfile of roombooking:

Code:
<many-to-one name="HotelBooking" column="HotelBookingId" class="Airtrade.Business.Hotels.HotelBooking,  Airtrade.Business.Hotels" />


So, there is the parent-object defined, but I try to only define the parent-key in the mapping which does not work..

Why do I want to remove the parent-object? because than in code, I also have to assign the correct parent-object. And I think it is strange to have to assign the parent to the child, if NHibernate can see the parent-child relation in the mappingfile?

Is it possible to remove the many-to-one from the child-mapping file or is it really needed in the mappingfile?

Hope someone can help me out,


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 08, 2006 5:34 pm 
Beginner
Beginner

Joined: Wed Nov 29, 2006 5:33 pm
Posts: 28
Location: Chicago, IL
When you create a bidirectional relationship in NHibernate, one end of that relationship must be marked as the inverse so that NHibernate does not try issuing two update staements on the same data. NHibernate does not support the inverse attribute in the many-to-one element though (to the best of my knowledge), which means that the one-to-many element should be declared as the inverse.

This leads to the situation where you need to set the parent item on the child. It may seem strange that this is preferable, but it will help your application perform better in most situations.

For the moment, lets say the the parent managed the persistence of the children. The parent already exists in the database with 20 children. I want to remove one child from that collection. The database must load all of those records from the database in order to let me choose which one to remove. If I wanted to add one child, the system would first need to retrieve all of them from the database before I added that one to the collection so that it knew if I meant to simply add one, or remove all items except for one.

Now look at it from the point of view of managing the relationship from the child. If I want to add one item, I set it's parent. None of the other items are affected. If I want to remove that item, I delete it or change its parent id. No extra reads from the database.

The only way I can think of to have the parent manage the relationship is to have a one way relationship which means the child will not contain a reference to the parent.

_________________
Chuck

Not in the face! Not in the face!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 10, 2006 6:04 am 
Beginner
Beginner

Joined: Thu Oct 26, 2006 4:45 am
Posts: 39
Thanks for your answer.

The thing is that I want to remove the parent-object from the class of the child-object, because collegues have made the mistake of programming against the parent object.

Like this:

HotelBooking hBooking = new hBooking
RoomBooking room = new RoomBooking
room.price = xxx
hBooking.RoomBookingList.Add(room)
...
... (have to add displayname for HotelBooking)
...
room.HotelBooking.DisplayName = "something"

I do not want my collegues to have that parent-reference in the child but want them to program directly against the parent and not 'via' the child.

If I understand your remark correctly, I do not want ro remove the parentreference from the child because of performance issues in the database. I guess I have to do more code-reviews than :)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 15, 2006 11:36 am 
Beginner
Beginner

Joined: Wed Nov 29, 2006 5:33 pm
Posts: 28
Location: Chicago, IL
Hello,

I can understand wanting to prevent people from coding against the parent's collection because then they don't understand why the item wasn't added to the collection when they load it from the database later.

What we do is make the collection itself a private field and only expose the collection as an enumerable generic. Then, in order to add and remove items from the collection, we provide accessor methods: AddChild, RemoveChild, etc. When someone calls AddChild we both add the item to the collection and set the parent of the child.

There are a few different ways of implementing the collection access. We went with enumerable generics because we use generics for everything in our business layer and it is working well enough. A better approach if you are not using generics is to create readonly ArrayLists (there are a few threads on the forum here about the subject). That way, there are fewer extra accessor methods that need to be created. At some point, I will probably try to find an implementation of a readonly IList generic and substitute that in. The list of possibilities goes on.

_________________
Chuck

Not in the face! Not in the face!


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