持久化模式,第 2 部分: 提高代码重用和改进性能
2010-04-02 00:00:00 来源:WEB开发网即时抓取正好与惰性抓取相反。当装载一个对象时,会立即装载标为即时抓取的所有关联。当装载单一对象时,运行的查询并不比使用惰性关联时少。但是,因为查询会立即运行,所以不会出现 LazyInitializationException异常。即时抓取还有助于解决 n+1 选择问题。如果Employee对象的Address 关联是即时的,并执行查询获取 10 个 Employee 实例时,只执行两个查询:一个查询获取 Employee 实例的列表,一个查询获取与 Employee 对象相关联的 Address 实例列表。Hibernate 会无缝地把这些列表合并在一起。
即时抓取可能不适合作为默认策略。如果过分频繁地使用这种策略,很容易导致装载大量不需要的数据。但是,有时候总是需要访问某个关联,在这种情况下使用即时抓取是有意义的。启用即时抓取的过程与启用惰性抓取基本相同。只需在注解中指定即时抓取:
@ManyToOne(fetch=FetchType.EAGER)
public void getAddress() {//...}
最佳实践和查询关联
Hibernate 为解决 惰性抓取的问题 提供了一个优雅的解决方案,同时保持惰性抓取的优点。Hibernate 允许查询的定义覆盖关联的默认抓取策略。可以在对对象树进行一般访问期间使用惰性抓取,但是在特殊情况下(在查询时已经知道需要使用关联),可以通过设置查询参数把关联标为即时的。例如,在职员示例程序中,可能需要查询在一段时期内工作了特定小时数的所有职员,以便生成邮件标签。清单 8 中的查询可以完成这个任务:
清单 8. 覆盖默认的抓取策略
Criteria addressCrit = empCrit.createCriteria("payChecks")
.add(Restrictions.eq("hoursWorked", hoursParam));
empCrit.setFetchMode("address",FetchMode.JOIN);
return empCrit.list();
更多精彩
赞助商链接