19. 提升性能 / 19.1. 抓取策略(Fetching strategies) / 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次查询的方法是,使用二级缓存。