[注: 文中用到的例子对象和配置文件都在前面Hibernate学习笔记系列中提到过, 包含域对象,dao, 映射文件,DML语句.如果有看不明白,请参看前面的文章]
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)。
下面根据关联关系的不同,分情况讨论一下检索策略和抓取方式的应用。
多对一(many-to-one):应该优先考虑预先抓取,他比立即检索少使用了sql, 有助于提高性能。但是fetch和lazy可以有不同的组合, Order和Member是Many-to-one关系,下面是Order.hbm.xml和Member.hbm.xml配置上不同的组合产生的检索策略:
Order.hbm.xml的<many-to-one> 节点的fetch属性 | Order.hbm.xml的<many-to-one>
节点的lazy属性 |
Member.hbm.xml的<class> 节点的lazy属性 | 检索策略 |
/ | false | / | 立即检索 |
/ | proxy | true | 延迟加载 |
join | / | false | 预先抓取 |
无 | 无 | false | 预先抓取 |
select | / | false | 立即检索 |
"/"表示此属性可为人意值, "无"表示此节点不加此属性.
一对一(one-to-one): 应该优先考虑预先抓取,而且hibernate默认是预先抓取.Member和IDCard是one-to-one关系,下面以Member.hbm.xml和IDCard.hbm.xml的配置的不同来产生不同的策略:
Member.hbm.xml的<one-to-one> 节点的fetch属性 | Member.hbm.xml的<one-to-one>
节点的lazy属性 |
IDCard.hbm.xml的<class> 节点的lazy属性 | 检索策略 |
/ | true | true | 立即检索 |
join | false | / | 预先抓取 |
无 | 无 | 无 | 预先抓取 |
select | / | / | 立即检索 |
"/"表示此属性可为人意值, "无"表示此节点不加此属性.
可以看到上面没有提到延迟加载,是因为hibernate one-to-one的实现比较特殊,要设置<one-to-one>的constrained='true', 同时被关联的class的lazy='true'.
一对多/多对多(one-to-many/many-to-many): 优先考虑延迟加载.
<one-to-many> / <many-to-many>的fetch |
<one-to-many> / <many-to-many>的lazy | 立即检索 | |
join | / | 预先抓取 | |
select | false | 立即检索 | |
select | true | 延迟加载 |
"/"表示此属性可为人意值, "无"表示此节点不加此属性.