如何让 Hibernate 在 WebLogic 10g 上对每个父/子关系执行不超过一个 SQL 查询?
我们需要取回 Widget 的集合,其中每个 widget 可以包含零个或多个 Fidget。我们的问题是,每当我们从 Widget 运行时,Hibernate 都会为每个 Widget 上的每个 Fidget 生成一个 SQL 查询。因此,如果我有一个带有 19 个 Fidgets 的 Widget,Hibernate 将运行 20 个 SQL 查询!我预计只有两个查询:一个针对 Widget,另一项针对 Fidgets。
我们有 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>
Hibernate 为具有四个 Fidget 的 Widget 和一个具有六个 Fidget 的 Widget 生成以下 SQL:
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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
启用批量获取 Hibernate 配置以减少查询数量,或执行将加载小部件及其 Fidgets 的查询:
这在 参考文档,这是一个很好的来源的信息。
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:
This is also well described in the reference documentation, which is a great source of information.