-->
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.  [ 13 posts ] 
Author Message
 Post subject: Indexed Collection
PostPosted: Mon Oct 24, 2005 6:35 pm 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
I am wondering what is the best way to map a one to many assosciation that needs to keep track of its index within the collection. This collection may contain a large number of entities. Also each entity needs to know its position within the collection even if its accessed outside of the collection. For instance, this entity needs to know that it is "Step" #5 in the collection of steps it belongs to if it was simply pulled up by its Id as opposed to direct navigation through the parent entities Steps collection.

I am trying a <list> mapping but that doesnt seem to work properly. I am getting a null reference excpetion down in NHibernate.Impl.SessionImpl.GetPersister.

I also read in Hibernate in Action that you cant use indexed collections on the inverse side of an assosciation.

Whats the solution here? Do i have to manage the index myself?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 25, 2005 9:35 pm 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
I cant even get a <list> mapping to update the index of the object at all. I keep getting an a sql error stating that the 'Sequence' column can not be null. 'Sequence' is my index in the database. Here is my mapping:

Code:
<list name="Steps" lazy="true" cascade="all-delete-orphan" access="field.camelcase-underscore">
  <key>
    <column name="ProcedureId" not-null="true" />
  </key>
  <index column="Sequence" />
  <one-to-many class="Step" />
</list>


Do I have something wrong? Shouldn't Nhibernate be handling the update and insert of the 'Sequence' column?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 27, 2005 2:40 am 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
I got this working, it appears that the index and foreign key columns must be nullable in order to use the <list> mapping. This seems very odd to me, especially the foreign key part. On collection modifications, I see that NHibernate first issues a query to set the parent id(foreign key) and index column to null and then updates them accordingly? What is the need to set these columns to null and then update them? Seems like extra db work for no reason.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 07, 2005 3:26 am 
Newbie

Joined: Wed Oct 12, 2005 4:36 am
Posts: 9
I can not get the list to work ; I am using list to keep indexes too; i managed to save the list objects successfully "not straight forward though" to the database but can not load list objects back at all

I have these classes

Code:

Class Base
{
       private string mID;
       public string ID
      {
          get {return mID;}
          set {mID = valuse}
      }
}
Class A : Base
{
     private IList mBs;
     public IList Bs
     {
          get{return mName;}
          set{mName = value;}
     }   
}

Class B : Base
{
      private A mParentA;
      public A ParentA
      {
            get {return mParentA;}
            set {mParentA = value;}
      }
}



And the mappings for them are

Code:

<class name="DataModel.Base, DataModelDemo" table="Base">
      <id name="ID">
         <generator class="assigned"/>
      </id>
</class>

<joined-subclass name="DataModel.A, DataModelDemo" table="A" extends="DataModel.Base, DataModelDemo">
   <key column="UID"/>
   <list name="Bs" cascade="all" table="B" inverse="false">
      <key column="A_ID"/>
      <index column="seq"/>
      <one-to-many class="DataModel.B, DataModelDemo"/>
   </list>
</joined-subclass>

<joined-subclass name="DataModel.B, DataModelDemo" table="B" extends="DataModel.Base, DataModelDemo" dynamic-insert="true" dynamic-update="true" lazy="false">
   <key column="ID" />
   <many-to-one name="ParentA" column="A_ID" not-null="true" cascade="none"/>
</joined-subclass>


--1--now this code does not work properly I got no exceptions but when I add an instance of class A to the session the IList turns to undefined value !! can i keep the array list ???

--2-- so I have to reinitialize it again and then add instances of class B to the List "This does not add them to database" is there persistence by reachability ?

so i added each instance of class B to the session and then commited the session which then added the Bs to database successfully

--3-- now i try to retrieve A object from database using
Code:
nhSession.CreateCriteria(typeof(DataModel.A)).List();


this retrieves the A's objects successfully but with undefined lists !!!!!

I tried
Code:
NHibernateUtil.Initialize(AObject);
OR
NHibernateUtil.Initialize(aObject.Bs);


With no success always undefined list;

Clearly I am missing something ,,, Any help is appreciated;
Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 18, 2005 2:54 pm 
Newbie

Joined: Wed Nov 16, 2005 2:40 pm
Posts: 19
Location: Palo Alto, CA
alsilk wrote:
I can not get the list to work ; I am using list to keep indexes too; i managed to save the list objects successfully "not straight forward though" to the database but can not load list objects back at all


Did you ever figure out what went wrong? I am having exactly the same symptoms.

Thanks!

Gene


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 19, 2005 8:05 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Bidirectional associations (for example, parent-children with children having a pointer back to the parent) cannot be mapped using indexed collections (lists, maps). This is not supported in the current version of NHibernate.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 19, 2005 6:17 pm 
Newbie

Joined: Wed Nov 16, 2005 2:40 pm
Posts: 19
Location: Palo Alto, CA
sergey wrote:
Bidirectional associations (for example, parent-children with children having a pointer back to the parent) cannot be mapped using indexed collections (lists, maps). This is not supported in the current version of NHibernate.


I am trying to represent a relationship that is not bi-directional, but am running into an apparent bug in the CascadeCollection method: it persists the objects in my list, but it does not set the field that identifies the parent (container) object. My quick stepping through the code didn't reveal any obvious place where that information would be persisted if it was not represented in the objects contained in the collection .

What am I missing?

Gene


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 20, 2005 5:07 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Eh, if you have a "field that identifies the parent (container) object", then you do have a bi-directional association. And you have to set the reference yourself, NHibernate doesn't do it by design.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 20, 2005 3:22 pm 
Newbie

Joined: Wed Nov 16, 2005 2:40 pm
Posts: 19
Location: Palo Alto, CA
sergey wrote:
Eh, if you have a "field that identifies the parent (container) object", then you do have a bi-directional association. And you have to set the reference yourself, NHibernate doesn't do it by design.


I am sure I am misunderstanding the intent of the List or Bag declaration, but doesn't the Key attribute cause a field to be added to the table of the contained object? That field doesn't exist in the object's DOM, and is rightly the responsibility of the List/Bag. But I cannot create a List/Bag without a Key declaration. So does this mean that for every container object that contains instances of my object, I have to have a separate field (that I have to set manually) in my contained object? Doesn't the break the design goal of not having to modify the DOM to obtain persistence? Why wouldn't the collection's state be used to persist the contained objects in a cascade operation? Perhaps I am just terribly confused about how this is done...

Gene


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 21, 2005 2:35 am 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
I am running into the same (or similar) problem that gene is. First, I think I need some clarification; I was under the impression that an association was not bi-directional until you put the inverse="true" attribute in the collection side of the association. Without that attribute it is simply a one-way association that you as the programmer have to manage. (See p109 of the Hibernate in Action book for my reference.)

As such I have a "Step" class:

Code:
<list name="Objectives" table="WMPObjective" cascade="none" lazy="true" access="nosetter.camelcase">
   <key column="StoneID" />
   <index column="SortOrder" />
   <one-to-many class="Objective" />
</list>


and I have an Objective class:

Code:
<many-to-one name="Stone" class="Stone" column="StoneID" />


Indeed, as gene mentions, when I am updating the indexed collection, NH first wants to set the StoneID (and SortOrder) to NULL and then follows up with a second update that sets the StoneID and SortOrder appropriately. This seems superfluous to me so I figure I must be missing something. Obviously I don't want StoneID to be NULLable.

Basically, I think the first post said it best:

Quote:
what is the best way to map a one to many assosciation that needs to keep track of its index within the collection


Cheers,

-devon


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 21, 2005 11:37 am 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
I had forgotten about this, but definately this functionality is not supported in this version of NHibernate. There is a JIRA. For those that really want this issue to be resolved, please vote for it:

http://jira.nhibernate.org/browse/NH-298
http://www.hibernate.org/193.html

This has been implemented in Hibernate3 so it might be somewhat easier now. In the meantime, as I mention in the JIRA, the easiest (although not very clean) method I have found is to copy the array, update the copied array, delete the child collection from the parent object and then replace the parent.Child collection with the copied array. This gets around the NULL foreignkey and ordering columns...

-devon


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 23, 2005 12:34 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
gene wrote:
I am sure I am misunderstanding the intent of the List or Bag declaration, but doesn't the Key attribute cause a field to be added to the table of the contained object? That field doesn't exist in the object's DOM, and is rightly the responsibility of the List/Bag.


I misunderstood you. If you mean the database field is not being set, it's normal because the collection is managed by the parent object, so when the parent is saved, the collection is saved too, and the collection persister then updates the child foreign key fields.

gene wrote:
But I cannot create a List/Bag without a Key declaration. So does this mean that for every container object that contains instances of my object, I have to have a separate field (that I have to set manually) in my contained object?


Not necessarily, but there are tradeoffs involved. You can do without the back pointer if you allow the parent foreign key in the child table to be null.

gene wrote:
Doesn't the break the design goal of not having to modify the DOM to obtain persistence? Why wouldn't the collection's state be used to persist the contained objects in a cascade operation? Perhaps I am just terribly confused about how this is done...


Hibernate 3 actually removed this limitation. I guess it was done this way in H2 because it was simpler and faster.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 23, 2005 4:43 pm 
Newbie

Joined: Wed Nov 16, 2005 2:40 pm
Posts: 19
Location: Palo Alto, CA
It turns out that the problem was a missing Flush() call. Thanks to Sergey for pointing this out in another thread. (See http://forum.hibernate.org/viewtopic.php?t=953228)

Gene


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