-->
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.  [ 2 posts ] 
Author Message
 Post subject: Need help on ICriteria query with fetch=join
PostPosted: Wed May 09, 2007 9:27 am 
Regular
Regular

Joined: Tue Feb 21, 2006 9:50 am
Posts: 107
Hi all,

i'm working on optimizing an application using NHibernate 1.0.4 and SQL-Server 2000.

I have problems with an ICriteria query on an object which contains one-to-one mappings. Regardless what FetchMode i configure NHibernate uses the 'fetch="select"' mode which leads to the well known n+1 select problem.

Here is my code (mappings are shortened because of the number of fields in the tables):

Code:
Mappings:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" assembly="MyAssembly" namespace="MyNamespace">
  <class name="Material" table="MATERIAL">
    <id name="mId" column="MATERIAL_ID" access="field" type="Guid">
      <generator class="guid"/>
    </id>
    <many-to-one name="Autopull" column="AUTOPULL_ID" class="myNamespace.Autopull" unique="true" fetch="join" cascade="all-delete-orphan" />
    ...
    field mapping for MATERIAL
    ...
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" assembly="MyAssembly" namespace="MyNamespace">
  <class name="Autopull" table="AUTOPULL">
    <id name="mId" column="AUTOPULL_ID" access="field" type="Guid">
      <generator class="guid"/>
    </id>
    <many-to-one name="OptionalAutopull" column="OPTIONAL_AUTOPULL_ID" class="Mynamespace.OptionalAutopull" unique="true" cascade="none" />
    <one-to-one name="Material" class="Mynamespace.Material" property-ref="Autopull" fetch="join" />
    ...
    field mapping for AUTOPULL
    ...
  </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" assembly="MyAssembly" namespace="MyNamespace">
  <class name="OptionalAutopull" table="OPTIONAL_AUTOPULL">
    <id name="mId" column="OPTIONAL_AUTOPULL_ID" access="field" type="Guid">
      <generator class="guid"/>
    </id>
    ...
    field mapping for AUTOPULL
    ...
  </class>
</hibernate-mapping>

Code:

IList materials = session.CreateCriteria(typeof(Material))
  .Add(Expression.In(Material.CUSTOMER_ID, pCustomerIds))
  .Add(Expression.In(Material.MATERIAL_CLASSIFICATION_CODE, getConfigMaterialClassificationCodes()))
  .Add(Expression.Eq(Material.CONFIGURED_MATERIAL_FLAG, new NullableBoolean(false)))
  .SetFetchMode("Autopull", FetchMode.Join)
  .SetFetchMode("Autopull.Material", FetchMode.Join)
  .List();

The generated select looks like this:

Code:
first select:

SELECT
  <field_list>
FROM
  MATERIAL this
  left outer join AUTOPULL autopul1_ on this.AUTOPULL_ID=autopul1_.AUTOPULL_ID
  left outer join MATERIAL gdcmateria2_ on autopul1_.AUTOPULL_ID=materia2_.AUTOPULL_ID
  left outer join OPTIONAL_AUTOPULL optiona3_ on autopul1_.OPTIONAL_AUTOPULL_ID=optiona3_.OPTIONAL_AUTOPULL_ID
WHERE
  <selection_criteria>

subsequent selects:

SELECT
  <field_list>
FROM
  MATERIAL materia0_
  left outer join AUTOPULL gdcautopul1_ on materia0_.AUTOPULL_ID=autopul1_.AUTOPULL_ID
  left outer join MATERIAL materia2_ on autopul1_.AUTOPULL_ID=materia2_.AUTOPULL_ID
  left outer join OPTIONAL_AUTOPULL optiona3_ on autopul1_.OPTIONAL_AUTOPULL_ID=optiona3_.OPTIONAL_AUTOPULL_ID
WHERE
  materia0_.AUTOPULL_ID=@p0

The first select returns all data nHibernate needs to initialize the objects. The second select NHibernate generates for each Autopull found to fill the Material property. If i look at the internal structures i will find all objects filled except the fields which build up the one-to-one mapping.

I have debugged NHibernate and didn't find where the .SetFetchMode() of the ICriteria or the "fetch=join" was evaluated. No matter what i configure, NHibernate does the n+1 select.

If i remove the <one-to-one> from the Autopull mapping, NHibernate executes only one select against the database. But i need the bidirectional reference in my business logic.

Did anyone have a hint how i can solve this problem?

The only thing which springs to my mind is to map the AUTOPULL table as component instead of one-to-one, as Autopulls are just an enhancement to Materials. But if i do so this will lead to a lot of code changes.

Many thanks in advance
Klaus


Top
 Profile  
 
 Post subject:
PostPosted: Sat May 12, 2007 12:05 am 
Regular
Regular

Joined: Tue Feb 21, 2006 9:50 am
Posts: 107
Hi,

did anybody have a hint to solve my problem?

Thanks in advance
Klaus


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