19.1.2. 调整抓取策略(Tuning fetch strategies)
查询抓取(默认的)在N+1查询的情况下是极其脆弱的,因此我们可能会要求在映射文档中定义使用连接抓取:
<set name="permissions"
fetch="join">
<key column="userId"/>
<one-to-many class="Permission"/>
</set
<many-to-one name="mother" class="Cat" fetch="join"/>
在映射文档中定义的抓取
策略将会对以下列表条目产生影响:
通过
get()
或load()
方法取得数据。只有在关联之间进行导航时,才会隐式的取得数据。
条件查询
使用了
subselect
抓取的HQL查询
不管你使用哪种抓取策略,定义为非延迟的类图会被保证一定装载入内存。注意这可能意味着在一条HQL查询后紧跟着一系列的查询。
通常情况下,我们并不使用映射文档进行抓取策略的定制。更多的是,保持其默认值,然后在特定的事务中, 使用HQL的左连接抓取(left join fetch)
对其进行重载。这将通知 Hibernate在第一次查询中使用外部关联(outer join),直接得到其关联数据。 在条件查询
API中,应该调用 setFetchMode(FetchMode.JOIN)
语句。
也许你喜欢仅仅通过条件查询,就可以改变get()
或 load()
语句中的数据抓取策略。例如:
User user = (User) session.createCriteria(User.class)
.setFetchMode("permissions", FetchMode.JOIN)
.add( Restrictions.idEq(userId) )
.uniqueResult();
(这就是其他ORM解决方案的“抓取计划(fetch plan)”在Hibernate中的等价物。)
截然不同的一种避免N+1次查询的方法是,使用二级缓存。