http://www.javaeye.com/topic/77475
在hibernate3里面多了 fetch的选项,文档里面说得很简单,我知道lazy参数才是决定是否在查询主表的时候去查询子表,但是这个 fetch又起什么作用呢?我测试了一下,发现无论是 fetch="join" 还是 fetch="select",hibernate向数据库发送的 SQL都是一样的。 以一个简单的一对多做例子:
Many 一端
- <hibernate-mapping>
- <class name="lyo.test.hibernate.bean.PostThread" table="thread" catalog="testrails">
- <id name="id" type="java.lang.Integer">
- <column name="id" />
- <generator class="native" />
- </id>
- <many-to-one name="developer" class="lyo.test.hibernate.bean.Developer"
- lazy="false" fetch="join">
- <column name="developer_id">
- <comment></comment>
- </column>
- </many-to-one>
- </class>
- </hibernate-mapping>
<hibernate-mapping> <class name="lyo.test.hibernate.bean.PostThread" table="thread" catalog="testrails"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="native" /> </id><many-to-one name="developer" class="lyo.test.hibernate.bean.Developer" lazy="false" fetch="join"> <column name="developer_id"> <comment></comment> </column> </many-to-one> </class></hibernate-mapping>
One 一端:
- <hibernate-mapping>
- <class name="lyo.test.hibernate.bean.Developer" table="developer" catalog="testrails">
- <id name="id" type="java.lang.Integer">
- <column name="id" />
- <generator class="native" />
- </id>
- <set name="threads" inverse="true" cascade="all">
- <key>
- <column name="developer_id">
- <comment></comment>
- </column>
- </key>
- <one-to-many class="lyo.test.hibernate.bean.PostThread" />
- </set>
- </class>
- </hibernate-mapping>
<hibernate-mapping> <class name="lyo.test.hibernate.bean.Developer" table="developer" catalog="testrails"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="native" /> </id> <set name="threads" inverse="true" cascade="all"> <key> <column name="developer_id"> <comment></comment> </column> </key> <one-to-many class="lyo.test.hibernate.bean.PostThread" /> </set> </class></hibernate-mapping>
测试查询语句:
- List list=session.createQuery("from PostThread").list();
List list=session.createQuery("from PostThread").list();
发现 hibernate向数据库发送的语句都是:
- 07:45:11,471 DEBUG org.hibernate.hql.ast.QueryTranslatorImpl.generate:217 - SQL: select postthread0_.id as id0_, postthread0_.developer_id as developer10_0_ from testrails.thread postthread0_
07:45:11,471 DEBUG org.hibernate.hql.ast.QueryTranslatorImpl.generate:217 - SQL: select postthread0_.id as id0_, postthread0_.developer_id as developer10_0_ from testrails.thread postthread0_
怎么会没有区别呢? 文档上好像说 join的方式效率高一些,但是是否取子表的数据不是由 lazy参数决定的么,和 fetch 参数有什么关系?
答:
fetch参数指定了关联对象抓取的方式是select查询还是join查询,select方式时先查询返回要查询的主体对象(列表),再根据关联外键id,每一个对象发一个select查询,获取关联的对象,形成n+1次查询;
而join方式,主体对象和关联对象用一句外键关联的sql同时查询出来,不会形成多次查询。
如果你的关联对象是延迟加载的,它当然不会去查询关联对象。
另外,在hql查询中配置文件中设置的join方式是不起作用的(而在所有其他查询方式如get、criteria或再关联获取等等都是有效的),会使用select方式,除非你在hql中指定join fetch某个关联对象。
fetch策略用于定义 get/load一个对象时,如何获取非lazy的对象/集合。 这些参数在Query中无效。