-->
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.  [ 5 posts ] 
Author Message
 Post subject: Batch Size problem/ N+1 SELECT Query
PostPosted: Thu Jan 10, 2008 1:03 pm 
Newbie

Joined: Sun May 14, 2006 8:48 am
Posts: 12
Hibernate version:1.2.0.4000
Mapping documents:Xml Configuration
Name and version of the database you are using:SQLServer 2005 Express Edition
-----------------------------------------------------------------
I have a problem when trying to display data paged.
when i call SetFirstResult and SetMaxResults, NH executes a query finding database identifiers in the range, then creates and executes n query based on n identifiers returned.

i thought "batch-size" attribute in class declaration in hbm configuration files can be used for that (i.e. instead of executing n queries, execute 1 query for all passing identifiers)
(13) batch-size (optional, defaults to 1) specify a "batch size" for fetching instances of this class by identifier. , NH doc, section 5.1.3 class

but after i applied batch to 10 or 25, no things differed. also i try below configuration '<add key="hibernate.batch_size" value="2">' in NH configuration. but nothing changed.

my question is: how can say NH to load 10 rows each time?

below is my class hbm:
--------------------------------------------------
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Mehan.Navand.EntityLayer" assembly="Mehan.Navand.EntityLayer">
   <class name="ContactEntity" table="OrmContacts_ContactsTable" batch-size="25">
      <id name="Id" type="string" unsaved-value="null">
         <generator class="uuid.hex" />
      </id>
      <version name="Version" unsaved-value="-1"/>
      <property name="CreationDate" type="datetime"/>
      <property name="Confirmed"/>
      <property name="BankName" />
      <property name="BankAccount" />
      <property name="BankCardNumber" />
      <property name="Birthday" type="datetime" />
      <property name="BusinessAddress" />
      <property name="BusinessAddressCity" />
      <property name="BusinessAddressProvience" />
      <property name="BusinessAddressCountry" />
      <property name="BusinessAddressStreet" />
      <property name="BusinessEmail" />
      <property name="BusinessFax" />
      <property name="BusinessName" />
      <property name="BusinessOrganization" />
      <property name="BusinessPhone" />
      <property name="BusinessRole" />
      <property name="BusinessUrl" />
      <property name="BusinessWeblog" />
      <property name="CellNumber" />
      <property name="ForeName" />
      <property name="GoogleId" />
      <property name="HomeAddress" />
      <property name="HomeAddressStreet" />
      <property name="HomeAddressCity" />
      <property name="HomeAddressProvience" />
      <property name="HomeAddressCountry" />
      <property name="HomeFax" />
      <property name="HomePhone" />
      <property name="IcqId" />
      <property name="LastName" />
      <property name="MarriageDate" type="datetime" />
      <property name="Memo" />
      <property name="NickName" />
      <property name="PersonalEmail" />
      <property name="PersonalUrl" />
      <property name="PersonalWeblog" />
      <property name="Title" />
      <property name="YahooId" />
      <property name="Gender" />
      <set name="Properties" cascade="all-delete-orphan" lazy="true">
         <key column="Contact"/>
         <one-to-many class="ContactPropertyEntity"/>
      </set>
      <bag name="Labels" lazy="true" table="OrmContacts_ContactLabelsTable">
         <key column="ContactId"/>
         <element type="string" column="Label"/>
      </bag>
      <many-to-one cascade="none" name="Owner" column="OwnerId" class="MemberEntity" />
   </class>
</hibernate-mapping>


thanks in advance


Last edited by behzadian on Thu Jan 10, 2008 1:28 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 10, 2008 1:26 pm 
Regular
Regular

Joined: Wed Jan 25, 2006 1:11 am
Posts: 118
Location: Copenhagen, Denmark
The batch-size in configuration is for batching inserts/updates as far as i know.

Im not quite sure what you want to accomplish, can you post the code you execute where you expect batching to kick in (Code between sessionFactory.openSession() and session.close())


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 10, 2008 2:47 pm 
Newbie

Joined: Sun May 14, 2006 8:48 am
Posts: 12
thanks jta .

below is simple of code. because real code uses nested methods, i use summary code that really will execute.

Code:
public IEnumerable<ContactEntity> GetContacts(string user, int startRowIndex, int maximumRows)
{
    string query="FROM ContactEntity AS ContactEntity WHERE Contact.Owner=?";

    IQuery iQuery = DatabaseManager.CurrentSession.CreateQuery(query);
    iQuery = iQuery.SetFirstResult(startRowIndex);
    iQuery = iQuery.SetMaxResults(maximumRows);
    iQuery = iQuery.SetParameter(0, user, NHibernateUtil.String);

    IEnumerable enumerable = iQuery.Enumerable();
    try {
       foreach (ContactEntity item in enumerable)
          yield return item;
    } finally {
        ((IDisposable)enumerable).Dispose();
    }
}

foreach(ContactEntity item in GetContacts("user",0,10)){
    Response.Write(item.Name+"<br/>");
}


for above code, NH generates 11 queries!
imagine when thousands of my website users (really near to 100+ online user) try to list their contacts!!!!!!

also about "batch-size", I'm confused! because everywhere i searched about that, i found "batch insert/update" but nh docs say another!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 10, 2008 3:32 pm 
Regular
Regular

Joined: Wed Jan 25, 2006 1:11 am
Posts: 118
Location: Copenhagen, Denmark
Enumerable is used when you return data that might be cached or where you do not intend to use all the results. In your case List<T>() method may be better suited:

    public List<ContactEntity> GetContacts(string user, int startRowIndex, int maximumRows)
    {
    string query="FROM ContactEntity AS ContactEntity WHERE Contact.Owner=?";

    IQuery iQuery = DatabaseManager.CurrentSession.CreateQuery(query);
    iQuery = iQuery.SetFirstResult(startRowIndex);
    iQuery = iQuery.SetMaxResults(maximumRows);
    iQuery = iQuery.SetParameter(0, user, NHibernateUtil.String);
    return iQuery.List<ContactEntity>();
    }

    foreach(ContactEntity item in GetContacts("user",0,10)){
    Response.Write(item.Name+"<br/>");
    }


To learn more about Enumerable() brush up on chapter 9.3 in the nhibernate reference manual ;-)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 10, 2008 4:47 pm 
Newbie

Joined: Sun May 14, 2006 8:48 am
Posts: 12
Thanks jta,

You solved my problem!
1.5 years ago my application used NH1.0.2, and also IQuery.List(), but some errors will be generated like "You must close IDbReader before opening new sql command" (not accurate message, just thing i remember), for that i use enumeration method that allowed (and allow) me to dispose enumerable, meaning releasing database connection.

however after 1.5 years, i thought i must check it again!

thanks


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