Technorati 标签: hibernate, fetch, lazy

Hibernate 3.3.2.GA

hibernate检索策略是指hibernate加载关联对象的策略,hibernate3抓取关联对象有3种方式

 

连接抓取(join fetching):fetch="join", 在获取主对象的同时,通过外连接的方式获得关联对象,不会形成多次查询。
查询抓取(select fetching): fetch="select", 先获取主对象,然后根据关联id执行select查询获取关联对象。


子查询抓取 (subclass fetching): fetch="subselect", 通过子查旬而不是外连接获取关联对象。

检索策略是指在什么时候采用什么样的方式获取关联对象。有3 种:


立即检索(eager loading):在获取主对象的同时立即获得关联对象。一前面的one-to- many的Member和Order为例,一个Member对应多个Order.
<set name="orders" cascade="all" lazy="false">,则Member m = dao.getById(4);就会立即加载orders.


延迟加载(lazy loading):和立即检索相对应,只有在用到关联对象的时候才加载。
<set name="orders" cascade="all" lazy="true">,则Member m = dao.getById(4);就不会立即加载orders。


预先抓取(pre fetching):通过配置fetch="join",通过外连接获取关联对象。
<set name="orders" cascade="all" fetch="join"> 则Member m = dao.getById(4);hibernate通过left outer join获取orders.


抓取方式和检索策略这两种行为方式或者概念我混淆了好久。其实他们是不同的东西,需要多体会。通常改变fetch的取值会改变最终产生的sql,检索策略会影响关联对象的获取时机(也会影响到sql)。

fetch (optional - defaults to join): if set to join, the default, Hibernate will use an inner join to retrieve a <join> defined by a class or its superclasses. It will use an outer join for a <join> defined by a subclass. If set to select then Hibernate will use a sequential select for a <join> defined on a subclass. This will be issued only if a row represents an instance of the subclass. Inner joins will still be used to retrieve a <join> defined by the class and its superclasses.

下面根据关联关系的不同,分情况讨论一下检索策略和抓取方式的应用。


多对一(many- to-one):应该优先考虑预先抓取,他比立即检索少使用了sql, 有助于提高性能。但是fetch和lazy可以有不同的组合

 

一对一(one-to-one): 应该优先考虑预先抓取,而且hibernate默认是预先抓取. hibernate one-to-one的实现比较特殊,要设置<one-to-one>的constrained='true',  同时被关联的class的lazy='true'.

 

一对多/多对多(one-to-many/many-to-many): 优先考虑延迟加载.

 

fetch(可选-默认值是join):如果设置为join,hibernate将使用inner join(内连接)

如果关联的字段被设置为 not-null = “true” ,则为内连接的方式获取关联对象如

如果不设置not-null,则采用 left outer join的方式获取关联对象

 

fetch="select " 是用来告诉Hibernate,在查询超类时, 不要使用外部连接(outer join)来抓取子类的数据。