Hibernate之多端加载优化
所谓多端加载优化是指:一方为主加载对象,而多方为从加载对象,对于多方加载时的进行的延迟加载配置,鉴于此,fetch(加载方式)、lazy(加载时机)应设置在一方的关联属性中,即在集合set标签中:举个栗子
场景:一个国家(country)对应多个部长(minister),让其关联关系为双向关联。
实体类(Country.java)
package com.hibernate.beans;
import java.util.HashSet;
import java.util.Set;
public class Country {
private Integer cid;
private String cname;
private Set<Minister> ministers;
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public Country() {
ministers = new HashSet<Minister>();
}
public Country(String cname) {
this();
this.cname = cname;
}
@Override
public String toString() {
return "Country [cid=" + cid + ", cname=" + cname + "]";
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public Set<Minister> getMinisters() {
return ministers;
}
public void setMinisters(Set<Minister> ministers) {
this.ministers = ministers;
}
}
实体类(Minister.java)
package com.hibernate.beans;
/**
* 部长类
* @author Administrator
*
*/
public class Minister {
private Integer mid;
private Country country;
private String mame;
public Integer getMid() {
return mid;
}
public void setMid(Integer mid) {
this.mid = mid;
}
public Minister() {
super();
}
public Minister(String mame) {
super();
this.mame = mame;
}
public String getMane() {
return mame;
}
public void setMane(String mame) {
this.mame = mame;
}
public Country getCountry() {
return country;
}
/**
* 双关联要求只有一方输出对方即可,否则就会形成递归(玩完)
*/
@Override
public String toString() {
return "Minister [mid=" + mid + ", country=" + country + ", mame="
+ mame + "]";
}
public void setCountry(Country country) {
this.country = country;
}
}
映射文件(Country.hbm.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hibernate.beans">
<class name="Country" table="t_country">
<id name="cid" column="t_cid">
<!-- 主键生成策略 -->
<generator class="native"></generator>
</id>
<property name="cname" column="t_cname"></property>
<!-- fetch="join" lazy属性失效-->
<set name="ministers" cascade="save-update" lazy="true" fetch="select">
<key column="t_cid"></key>
<one-to-many class="Minister"/>
</set>
</class>
</hibernate-mapping>
映射文件(Minister.hbm.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hibernate.beans">
<class name="Minister" table="t_minister">
<id name="mid" column="t_mid">
<!-- 主键生成策略 -->
<generator class="native"></generator>
</id>
<property name="mane" column="t_mame"></property>
<many-to-one name="country" class="Country" cascade="save-update" column="t_cid"/>
</class>
</hibernate-mapping>
测试代码
public void testLayz(){
Session session = HbnUtils.getSession();
try{
session.beginTransaction();
Country country = session.get(Country.class, 1);
Set<Minister> ministers = country.getMinisters();
System.out.println(ministers.size()+"--------"+country.toString());
for (Minister minister : ministers) {
System.out.println(minister);
}
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}
}
分析原因
我在Country country = session.get(Country.class, 1)处设置一个断点,单步调试看其运行过程,发现
当运行完get方法时,只是查询了Country
select
country0_.t_cid as t_cid1_0_0_,
country0_.t_cname as t_cname2_0_0_
from
t_country country0_
where
country0_.t_cid=?
细看调试信息
继续执行Set<Minister> ministers = country.getMinisters();
仍旧没有查询
在往下:
select
ministers0_.t_cid as t_cid3_1_0_,
ministers0_.t_mid as t_mid1_1_0_,
ministers0_.t_mid as t_mid1_1_1_,
ministers0_.t_mame as t_mame2_1_1_,
ministers0_.t_cid as t_cid3_1_1_
from
t_minister ministers0_
where
ministers0_.t_cid=?
知道这个时候才进行了查询,因为访问到了详细信息——ministers.size()
这是延迟加载,也叫懒加载,还有一种更懒的方式
<set name="ministers" cascade="save-update" lazy="extra" fetch="select">
这个是能用聚合查询的就不用详情查询,真是懒到一定境界,优化就是这个意思,有优化性能才能更高,聚合查询查的是索引,效率不是一般的高!远远高于详情查询。