延迟抓取
默认 lazy=true
<bag name="childCategories" table="CATEGORY" cascade="save-update" inverse="true" lazy="true"> <key column="PARENT_CATEGORY_ID" /> <one-to-many class="cascade.Category" /> </bag>
parentCategory = (Category) session.get(Category.class, 1L);
parentCategory.getChildCategories();
Hibernate:
/* load cascade.Category */ select
category0_.CATEGORY_ID as CATEGORY1_0_0_,
category0_.CATEGORY_NAME as CATEGORY2_0_0_,
category0_.PARENT_CATEGORY_ID as PARENT3_0_0_
from
CATEGORY category0_
where
category0_.CATEGORY_ID=?
parentCategory = (Category) session.get(Category.class, 1L);
parentCategory.getChildCategories().size();
Hibernate:
/* load cascade.Category */ select
category0_.CATEGORY_ID as CATEGORY1_0_0_,
category0_.CATEGORY_NAME as CATEGORY2_0_0_,
category0_.PARENT_CATEGORY_ID as PARENT3_0_0_
from
CATEGORY category0_
where
category0_.CATEGORY_ID=?
Hibernate:
/* load one-to-many cascade.Category.childCategories */ select
childcateg0_.PARENT_CATEGORY_ID as PARENT3_0_1_,
childcateg0_.CATEGORY_ID as CATEGORY1_1_,
childcateg0_.CATEGORY_ID as CATEGORY1_0_0_,
childcateg0_.CATEGORY_NAME as CATEGORY2_0_0_,
childcateg0_.PARENT_CATEGORY_ID as PARENT3_0_0_
from
CATEGORY childcateg0_
where
childcateg0_.PARENT_CATEGORY_ID=?
lazy="extra" 如果调用size(),contains(),isEmpty()集合不在初始化
<bag name="childCategories" table="CATEGORY" cascade="save-update" inverse="true" lazy="extra"> <key column="PARENT_CATEGORY_ID" /> <one-to-many class="cascade.Category" /> </bag>
@OneToMany(mappedBy="parentCategory")
@Cascade({CascadeType.SAVE_UPDATE})
@org.hibernate.annotations.LazyCollection(LazyCollectionOption.EXTRA)
private List<Category> childCategories = new ArrayList<Category>();
lazy="false"禁用代理
<class name="cascade.Category" table="CATEGORY" lazy="false">
@org.hibernate.annotations.Proxy(lazy=false)
public class Category implements Serializable {
FetchType.EAGER提供与lazy='false'一样的保证
@OneToMany(mappedBy = "parentCategory",fetch=FetchType.EAGER)
@Cascade({ CascadeType.SAVE_UPDATE })
private List<Category> childCategories = new ArrayList<Category>();
FetchType.LAZY
通过拦截延迟加载
如果不想利用实体类的代理,依然想将延迟加载一个关联实体,可以用no-proxy映射这个关联
<many-to-one name="parentCategory" class="cascade.Category" cascade="none" lazy="no-proxy"> <column name="PARENT_CATEGORY_ID" not-null="false" /> </many-to-one>
@ManyToOne
@JoinColumn(name="SELLER_ID", nullable = false, updatable = false)
@org.hibernate.annotations.LazyToOne(
org.hibernate.annotations.LazyToOneOption.NO_PROXY
)
private User seller;
批量预抓取策略
<class name="cascade.Category" table="CATEGORY" batch-size="10"> <bag name="childCategories" table="CATEGORY" cascade="save-update" inverse="true" batch-size="10">
@org.hibernate.annotations.BatchSize(size=10)
public class Category implements Serializable {
@OneToMany(mappedBy = "parentCategory",fetch=FetchType.LAZY)
@Cascade({ CascadeType.SAVE_UPDATE })
@org.hibernate.annotations.BatchSize(size=10)
private List<Category> childCategories = new ArrayList<Category>();
子查询预抓取
<bag name="childCategories" table="CATEGORY" cascade="save-update" inverse="true" fetch="subselect">
@OneToMany(mappedBy = "parentCategory",fetch=FetchType.LAZY)
@Cascade({ CascadeType.SAVE_UPDATE })
@org.hibernate.annotations.Fetch(FetchMode.SUBSELECT)
private List<Category> childCategories = new ArrayList<Category>();
通过联接预抓取
<many-to-one name="parentCategory" class="cascade.Category" cascade="none" fetch="join"> <bag name="childCategories" table="CATEGORY" cascade="save-update" inverse="true" fetch="join">
fetch="join"禁用了延迟加载,通过联接及时抓取
@OneToMany(mappedBy = "parentCategory",fetch=FetchType.EAGER)
@Cascade({ CascadeType.SAVE_UPDATE })
private List<Category> childCategories = new ArrayList<Category>();
hibernate默认将其作为一个(JOIN)及时抓取
将联接抓取显示的转向一个立即的第二次查询
@OneToMany(mappedBy = "parentCategory",fetch=FetchType.EAGER)
@Cascade({ CascadeType.SAVE_UPDATE })
@org.hibernate.annotations.Fetch(FetchMode.SELECT)
private List<Category> childCategories = new ArrayList<Category>();
可以通过hibernate.max_fetch_depth配置联接表数量,通常在1~5之间
非全局的抓取策略
可以修改hql查询实现抓取策略
List<Item> allItems =
session.createQuery("from Item i left join fetch i.bids").list();
List<Item> allItems =session.createCriteria(Item.class)
.setFetchMode("bids", FetchMode.JOIN).list();
这两个查询通过out join为所有item实例生成了获取bid的单个select(fetch='join')