-->
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.  [ 8 posts ] 
Author Message
 Post subject: Fetching whole tree
PostPosted: Thu Jan 26, 2006 5:29 pm 
Regular
Regular

Joined: Tue Jan 03, 2006 11:43 am
Posts: 51
Location: Sweden
I have a table looking like this:

Node
------
(PK) id : int
parentId : int
treeId : int

Node is a recursive structure.
How would I do if I want to fetch a whole tree (all nodes with the same treeId) and get the root node (parentId = null) as efficiently as possible? Preferebly so it will only generate one SQL query.

/Carl


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 27, 2006 5:08 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Hmm, just load all nodes by treeId, take the first node out of the result and follow its parent property until it's null (should take only a few iterations if the tree is well-balanced).

Or, alternatively, select all nodes by treeId, order by parentId, then the root will be either the first or the last, depending on how your database sorts NULLs.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 27, 2006 10:52 am 
Regular
Regular

Joined: Tue Jan 03, 2006 11:43 am
Posts: 51
Location: Sweden
I tried this, but it does many selects..
In my code I use different names than above, but Container3 = Node, Scorecard = Tree.

This is how my mappings look like:
Code:
  <class name="Container3" table="Containers">
    <id name="Id" column="id">
      <generator class="native" />
    </id>   
    <many-to-one name="Parent"
          column="parentId"          
          class="Container3" />
    <bag name="Children" inverse="true">
      <key column="parentId" />
      <one-to-many class="Container3"/>
    </bag>   
    <property name="ScorecardId" column="scorecardId" />
  </class>

Code:
    public class Container3
    {
        private int m_id;

        public int Id
        {
            get { return m_id; }
            set { m_id = value; }
        }
        private Container3 m_parent;

        public Container3 Parent
        {
            get { return m_parent; }
            set { m_parent = value; }
        }
        private IList m_children;

        public IList Children
        {
            get { return m_children; }
            set { m_children = value; }
        }

        private int m_scorecardId;

        public int ScorecardId
        {
            get { return m_scorecardId; }
            set { m_scorecardId = value; }
        }
    }


And this the criteria:

Code:
         IList list = m_session.CreateCriteria(typeof(Container3))
                            .Add(Expression.Eq("ScorecardId", scorecardId))                           
                            .List();


The log:

NHibernate.Loader.Loader: 2006-01-27 15:45:00,599 [288] INFO NHibernate.Loader.Loader - SELECT this.id as id1_, this.parentId as parentId1_, this.scorecardId as scorecar5_1_, container31_.id as id0_, container31_.parentId as parentId0_, container31_.scorecardId as scorecar5_0_ FROM Containers this left outer join Containers container31_ on this.parentId=container31_.id WHERE this.scorecardId = @p0
NHibernate.Loader.Loader: 2006-01-27 15:45:00,630 [288] INFO NHibernate.Loader.Loader - SELECT children0_.parentId as parentId__, children0_.id as id__, children0_.id as id0_, children0_.parentId as parentId0_, children0_.scorecardId as scorecar5_0_ FROM Containers children0_ WHERE children0_.parentId=@p0
NHibernate.Loader.Loader: 2006-01-27 15:45:00,630 [288] INFO NHibernate.Loader.Loader - SELECT children0_.parentId as parentId__, children0_.id as id__, children0_.id as id0_, children0_.parentId as parentId0_, children0_.scorecardId as scorecar5_0_ FROM Containers children0_ WHERE children0_.parentId=@p0
NHibernate.Loader.Loader: 2006-01-27 15:45:00,645 [288] INFO NHibernate.Loader.Loader - SELECT children0_.parentId as parentId__, children0_.id as id__, children0_.id as id0_, children0_.parentId as parentId0_, children0_.scorecardId as scorecar5_0_ FROM Containers children0_ WHERE children0_.parentId=@p0
And so on...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 27, 2006 11:22 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
If you have the Children bag then it won't work so well, but if you declare the bag lazy you should avoid most of those extra selects (some will still remain).


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 27, 2006 12:00 pm 
Regular
Regular

Joined: Tue Jan 03, 2006 11:43 am
Posts: 51
Location: Sweden
With lazy I got it to do one select for the above criteria. But for each Node/Container3 I access after that I get a new select.. Why doesn't it take it from the cache?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 27, 2006 12:02 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Because it doesn't know that the whole collection is in the cache already. There's no way to tell NH that it is.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 27, 2006 12:05 pm 
Regular
Regular

Joined: Tue Mar 15, 2005 12:38 pm
Posts: 73
Location: Bucharest
Try using lazy with batch fetching to minimize the number of selects during tree traversal.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 27, 2006 12:07 pm 
Regular
Regular

Joined: Tue Jan 03, 2006 11:43 am
Posts: 51
Location: Sweden
Ok, thanks for straighting it out. I guess I will have to go with another approach (like fetching all Nodes and building the tree manually).

Btw, thanks for all the great work with NHibernate! I discovered it less than a month ago and it have already helped to speed up development a lot.


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