如何让Hibernate在WebLogic 10g上为每个父/子关系执行不超过一次的SQL查询?

问题描述:

我们需要找回一个Widget集合,其中每个Widget可以包含零个或多个Fidgets。我们的问题是,当我们运行from Widget时,Hibernate会为每个Widget上的每个Fidget生成一个SQL查询。所以如果我有一个包含19个Fidgets的Widget,Hibernate会运行20个SQL查询!我只希望只有两个查询:一个用于Widget,另一个用于Fidgets。如何让Hibernate在WebLogic 10g上为每个父/子关系执行不超过一次的SQL查询?

我们有SQL Server 2005和WebLogic 10g。

我相关的Spring配置:

<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> 

我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> 

我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> 

下面的SQL被产生Hibernate的一个Widget有四个Fidgets和一个Widget有六个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 
+3

问题标题有点误导。搜索“hibernate n + 1 select”;这是有据可查的。 –

+0

问题/回答这里跟Weblogic无关 –

在Hibernate配置启用batch fetching以减少查询的数量,或执行查询,将加载小工具及其坐立不安:

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

这也是公在reference documentation所描述的,这是一个很好的信息来源。

+0

感谢您的参考!通过在连接的末尾添加'fetch',我可以将它归结为一个SQL查询。 –