How to get Hibernate to do no more than one SQL query per a parent/child relationship on WebLogic 10g?

Question!

We need to get back a collection of Widgets, where each widget can contain zero or more Fidgets. Our problem is that whenever we run from Widget, Hibernate generates one SQL query for each Fidget on each Widget. So If I have one Widget with 19 Fidgets, Hibernate runs 20 SQL queries! I would have expected only two queries: one for the Widget and one for the Fidgets.

We have SQL Server 2005 and WebLogic 10g.

My relevant Spring Configuration:

<jee:jndi-lookup id="dataSourceA" jndi-name="jdbc/dataSourceA" />
<bean id="sessionFactoryA" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSourceA" />
    <property name="mappingResources">
        <list>
            <value>com/mycompany/database/Widget.hbm.xml</value>
            <value>com/mycompany/database/Fidget.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.query.factory_class=org.hibernate.hql.classic.ClassicQueryTranslatorFactory
            hibernate.dialect=org.hibernate.dialect.SQLServerDialect
            hibernate.show_sql=true
        </value>
    </property>
</bean>
<bean id="transactionManagerA" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactoryA" />
</bean>

My Widget.hbm.xml:

<class name="Widget" package="com.mycompany.database">
    <id name="id" column="ID" type="integer">
        <generator class="identity" />
    </id>
    ...
    <set name="fidgets" table="Fidget" lazy="false">
        <key column="WidgetID" />
        <one-to-many class="Fidget" />
    </set>
</class>

My Fidget.hbm.xml:

<class name="Fidget" package="com.mycompany.database">
    <id name="id" column="ID" type="integer">
        <generator class="identity" />
    </id>
    ...
    <many-to-one name="widget" column="WidgetID" class="Widget" lazy="false" />
</class>

The following SQL is generated by Hibernate for a Widget with four Fidgets and a Widget with six Fidgets:

select fidget_.Col1, fidget_.Col2, ... from Fidget fidget_ where fidget_.WidgetID = 7
select fidget_.Col1, fidget_.Col2, ... from Fidget fidget_ where fidget_.WidgetID = 7
select fidget_.Col1, fidget_.Col2, ... from Fidget fidget_ where fidget_.WidgetID = 7
select fidget_.Col1, fidget_.Col2, ... from Fidget fidget_ where fidget_.WidgetID = 7
select fidget_.Col1, fidget_.Col2, ... from Fidget fidget_ where fidget_.WidgetID = 8
select fidget_.Col1, fidget_.Col2, ... from Fidget fidget_ where fidget_.WidgetID = 8
select fidget_.Col1, fidget_.Col2, ... from Fidget fidget_ where fidget_.WidgetID = 8
select fidget_.Col1, fidget_.Col2, ... from Fidget fidget_ where fidget_.WidgetID = 8
select fidget_.Col1, fidget_.Col2, ... from Fidget fidget_ where fidget_.WidgetID = 8
select fidget_.Col1, fidget_.Col2, ... from Fidget fidget_ where fidget_.WidgetID = 8


Answers

Enable batch fetching in the Hibernate configuration to reduce the number of queries, or execute a query that will load the Widgets and their Fidgets:

select w from Widget w left join fetch w.fidgets where ...

This is also well described in the reference documentation, which is a great source of information.

By : JB Nizet


This video can help you solving your question :)
By: admin