所谓懒加载(lazy)就是延时加载,就是当在真正需要数据的时候,才真正执行数据加载操作

  至于为什么要用懒加载呢,就是当我们要访问的数据量过大时,明显用缓存不太合适,因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,我们让数据在需要的时候才进行加载,这时我们就用到了懒加载。

1.类级别的懒加载(session.load()方法)

  get方法:没有任何策略.调用即立即查询数据库加载数据.

  load方法: 应用类级别的加载策略

1.get方法测试,没有任何延迟加载策略

    @Test
// get方法 : 立即加载.执行方法时立即发送sql语句查询结果
public void fun1(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//---------------------------------------------------- Customer customer = session.get(Customer.class, 1l);//执行完此句即查询发出SQL System.out.println(customer);
//----------------------------------------------------
tx.commit();
session.close(); }

 

 没有延迟加载的get方法执行时候就发出SQL请求,且生成的对象是原生的JavaBean对象。

  

2.load方法测试,测试懒加载策略

修改配置文件懒加载设为true,默认就是开启懒加载的.比如我们查询customer的时候不会查询linkman,而我们调用get方法获取linkman的时候才去获取linkman。

    lazy(默认值):true, 查询类时,会返回代理对象.会在使用属性时,根据关联的session查询数据库.加载数据.

     lazy:false. load方法会与get方法没有任何区别.调用时即加载数据.

    结论:为了提高效率.建议使用延迟加载(懒加载)

原理:

  延迟加载是生成javaassist代理对象,生成代理对象的作用是依赖于session在使用对象的时候利用session去查询数据库,所以在使用懒加载时要确保,调用属性加载数据时,session还是打开的.不然会抛出异常

测试代码:

    @Test
// load方法(默认):是在执行时,不发送任何sql语句.返回一个对象.使用该对象时,才执行查询.
// 延迟加载: 仅仅获得没有使用.不会查询.在使用时才进行查询.
// 是否对类进行延迟加载: 可以通过在class元素上配置lazy属性来控制.
//lazy:true 加载时,不查询.使用时才查询
//lazy:false 加载时立即查询.
public void fun2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//---------------------------------------------------- Customer customer = session.load(Customer.class, 1l); System.out.println(customer);
//----------------------------------------------------
tx.commit();
session.close();
}

查看生成的代理对象:(代理对象的名称后面带有$符号)

注意:我们在使用懒加载的时候不能再关闭session之后再使用对象,因为懒加载的代理对象依赖session再使用对象的时候查询数据库,如下面的代码是错误的:

    public void fun2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//---------------------------------------------------- Customer customer = session.load(Customer.class, 1l); //----------------------------------------------------
tx.commit();
session.close();
System.out.println(customer);
}

结果会报错:

2.关联级别的查询(fetch、lazy、batch-size属性)

1.集合策略(根据客户关联查询联系人集合)

配置简介:

<?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="cn.qlq.domain" >
<class name="Customer" table="cst_customer" >
<id name="cust_id" >
<generator class="native"></generator>
</id>
<property name="cust_name" column="cust_name" >
</property>
<property name="cust_source" column="cust_source" ></property>
<property name="cust_industry" column="cust_industry" ></property>
<property name="cust_level" column="cust_level" ></property>
<property name="cust_linkman" column="cust_linkman" ></property>
<property name="cust_phone" column="cust_phone" ></property>
<property name="cust_mobile" column="cust_mobile" ></property> <!--
lazy属性: 决定是否延迟加载
true(默认值): 延迟加载,懒加载
false: 立即加载
extra: 极其懒惰
fetch属性: 决定加载策略.使用什么类型的sql语句加载集合数据
select(默认值): 单表查询加载
join: 使用多表查询加载集合
subselect:使用子查询加载集合
-->
<!-- batch-size: 抓取集合的数量为3.
抓取客户的集合时,一次抓取几个客户的联系人集合.
-->
<set name="linkMens">
<key column="lkm_cust_id" ></key>
<one-to-many class="LinkMan" />
</set>
</class>
</hibernate-mapping>

(1)fetch为select的测试:

  • lazy=true的测试
    // 集合级别的关联
// fetch:select 单表查询
// lazy:true 使用时才加载集合数据.
@Test
public void fun1() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- Customer c = session.get(Customer.class, 7l); Set<LinkMan> linkMens = c.getLinkMens();// 关联级别 System.out.println(linkMens);//打印SQL // ----------------------------------------------------
tx.commit();
session.close(); }

SQL:

Hibernate:
select
customer0_.cust_id as cust_id1_0_0_,
customer0_.cust_name as cust_nam2_0_0_,
customer0_.cust_source as cust_sou3_0_0_,
customer0_.cust_industry as cust_ind4_0_0_,
customer0_.cust_level as cust_lev5_0_0_,
customer0_.cust_linkman as cust_lin6_0_0_,
customer0_.cust_phone as cust_pho7_0_0_,
customer0_.cust_mobile as cust_mob8_0_0_
from
cst_customer customer0_
where
customer0_.cust_id=?
Hibernate:
select
linkmens0_.lkm_cust_id as lkm_cus10_1_0_,
linkmens0_.lkm_id as lkm_id1_1_0_,
linkmens0_.lkm_id as lkm_id1_1_1_,
linkmens0_.lkm_gender as lkm_gend2_1_1_,
linkmens0_.lkm_name as lkm_name3_1_1_,
linkmens0_.lkm_phone as lkm_phon4_1_1_,
linkmens0_.lkm_email as lkm_emai5_1_1_,
linkmens0_.lkm_qq as lkm_qq6_1_1_,
linkmens0_.lkm_mobile as lkm_mobi7_1_1_,
linkmens0_.lkm_memo as lkm_memo8_1_1_,
linkmens0_.lkm_position as lkm_posi9_1_1_,
linkmens0_.lkm_cust_id as lkm_cus10_1_1_
from
cst_linkman linkmens0_
where
linkmens0_.lkm_cust_id=?
[LinkMan [lkm_id=3, lkm_gender=null, lkm_name=王八, lkm_phone=null, lkm_email=null, lkm_qq=null, lkm_mobile=null, lkm_memo=null, lkm_position=null, customer=Customer [cust_id=7, cust_name=测试名称1]], LinkMan [lkm_id=4, lkm_gender=null, lkm_name=田七, lkm_phone=null, lkm_email=null, lkm_qq=null, lkm_mobile=null, lkm_memo=null, lkm_position=null, customer=Customer [cust_id=7, cust_name=测试名称1]]]
  • lazy=false的测试(会立即加载)
    // 集合级别的关联
// fetch:select 单表查询
// lazy:false 立即记载集合数据
@Test
public void fun2() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- Customer c = session.get(Customer.class, 7l);//加载所有SQL,包括查询linkman Set<LinkMan> linkMens = c.getLinkMens();// 关联级别 System.out.println(linkMens); // ----------------------------------------------------
tx.commit();
session.close(); }
  • lazy=xetra极其懒惰,与懒加载效果基本一致. 如果只获得集合的size.只查询集合的size(count语句)
    // 集合级别的关联
// fetch:select 单表查询
// lazy:extra 极其懒惰.与懒加载效果基本一致. 如果只获得集合的size.只查询集合的size(count语句)
@Test
public void fun3() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- Customer c = session.get(Customer.class, 7l); Set<LinkMan> linkMens = c.getLinkMens();// 关联级别 System.out.println(linkMens.size());//count SQL System.out.println(linkMens);//查询SQL // ----------------------------------------------------
tx.commit();
session.close(); }

SQL:

Hibernate:
select
customer0_.cust_id as cust_id1_0_0_,
customer0_.cust_name as cust_nam2_0_0_,
customer0_.cust_source as cust_sou3_0_0_,
customer0_.cust_industry as cust_ind4_0_0_,
customer0_.cust_level as cust_lev5_0_0_,
customer0_.cust_linkman as cust_lin6_0_0_,
customer0_.cust_phone as cust_pho7_0_0_,
customer0_.cust_mobile as cust_mob8_0_0_
from
cst_customer customer0_
where
customer0_.cust_id=?
Hibernate:
select
count(lkm_id)
from
cst_linkman
where
lkm_cust_id =?
2
Hibernate:
select
linkmens0_.lkm_cust_id as lkm_cus10_1_0_,
linkmens0_.lkm_id as lkm_id1_1_0_,
linkmens0_.lkm_id as lkm_id1_1_1_,
linkmens0_.lkm_gender as lkm_gend2_1_1_,
linkmens0_.lkm_name as lkm_name3_1_1_,
linkmens0_.lkm_phone as lkm_phon4_1_1_,
linkmens0_.lkm_email as lkm_emai5_1_1_,
linkmens0_.lkm_qq as lkm_qq6_1_1_,
linkmens0_.lkm_mobile as lkm_mobi7_1_1_,
linkmens0_.lkm_memo as lkm_memo8_1_1_,
linkmens0_.lkm_position as lkm_posi9_1_1_,
linkmens0_.lkm_cust_id as lkm_cus10_1_1_
from
cst_linkman linkmens0_
where
linkmens0_.lkm_cust_id=?

(2)fetch为join的多表查询: 延迟策略失效

    // 集合级别的关联
// fetch:join 多表查询
// lazy:true|false|extra 失效.立即加载.
@Test
public void fun4() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- Customer c = session.get(Customer.class, 7l); Set<LinkMan> linkMens = c.getLinkMens();// 关联级别 System.out.println(linkMens.size()); System.out.println(linkMens); // ----------------------------------------------------
tx.commit();
session.close(); }

SQL:

    select
customer0_.cust_id as cust_id1_0_0_,
customer0_.cust_name as cust_nam2_0_0_,
customer0_.cust_source as cust_sou3_0_0_,
customer0_.cust_industry as cust_ind4_0_0_,
customer0_.cust_level as cust_lev5_0_0_,
customer0_.cust_linkman as cust_lin6_0_0_,
customer0_.cust_phone as cust_pho7_0_0_,
customer0_.cust_mobile as cust_mob8_0_0_,
linkmens1_.lkm_cust_id as lkm_cus10_1_1_,
linkmens1_.lkm_id as lkm_id1_1_1_,
linkmens1_.lkm_id as lkm_id1_1_2_,
linkmens1_.lkm_gender as lkm_gend2_1_2_,
linkmens1_.lkm_name as lkm_name3_1_2_,
linkmens1_.lkm_phone as lkm_phon4_1_2_,
linkmens1_.lkm_email as lkm_emai5_1_2_,
linkmens1_.lkm_qq as lkm_qq6_1_2_,
linkmens1_.lkm_mobile as lkm_mobi7_1_2_,
linkmens1_.lkm_memo as lkm_memo8_1_2_,
linkmens1_.lkm_position as lkm_posi9_1_2_,
linkmens1_.lkm_cust_id as lkm_cus10_1_2_
from
cst_customer customer0_
left outer join
cst_linkman linkmens1_
on customer0_.cust_id=linkmens1_.lkm_cust_id
where
customer0_.cust_id=?

(3)fetch为subselect (只有在批量查询的时候才有用,如果是查询单个的话与select的作用一样)

  • lazy为true
    @Test
// fetch: subselect 子查询
// lazy: true 懒加载
public void fun5() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- String hql = "from Customer"; Query query = session.createQuery(hql); List<Customer> list = query.list(); for (Customer c : list) {
System.out.println(c);
System.out.println(c.getLinkMens().size());
System.out.println(c.getLinkMens());
} // ----------------------------------------------------
tx.commit();
session.close(); }

SQL:

Hibernate:
select
customer0_.cust_id as cust_id1_0_,
customer0_.cust_name as cust_nam2_0_,
customer0_.cust_source as cust_sou3_0_,
customer0_.cust_industry as cust_ind4_0_,
customer0_.cust_level as cust_lev5_0_,
customer0_.cust_linkman as cust_lin6_0_,
customer0_.cust_phone as cust_pho7_0_,
customer0_.cust_mobile as cust_mob8_0_
from
cst_customer customer0_
Customer [cust_id=7, cust_name=测试名称1]
Hibernate:
select
linkmens0_.lkm_cust_id as lkm_cus10_1_1_,
linkmens0_.lkm_id as lkm_id1_1_1_,
linkmens0_.lkm_id as lkm_id1_1_0_,
linkmens0_.lkm_gender as lkm_gend2_1_0_,
linkmens0_.lkm_name as lkm_name3_1_0_,
linkmens0_.lkm_phone as lkm_phon4_1_0_,
linkmens0_.lkm_email as lkm_emai5_1_0_,
linkmens0_.lkm_qq as lkm_qq6_1_0_,
linkmens0_.lkm_mobile as lkm_mobi7_1_0_,
linkmens0_.lkm_memo as lkm_memo8_1_0_,
linkmens0_.lkm_position as lkm_posi9_1_0_,
linkmens0_.lkm_cust_id as lkm_cus10_1_0_
from
cst_linkman linkmens0_
where
linkmens0_.lkm_cust_id in (
select
customer0_.cust_id
from
cst_customer customer0_
)
  • lazy为false,立即加载
    @Test
// fetch: subselect 子查询
// lazy: false 立即加载
public void fun6() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- String hql = "from Customer"; Query query = session.createQuery(hql); List<Customer> list = query.list(); for (Customer c : list) {
System.out.println(c);
System.out.println(c.getLinkMens().size());
System.out.println(c.getLinkMens());
} // ----------------------------------------------------
tx.commit();
session.close(); }
  • lazy为extra
    @Test
// fetch: subselect 子查询
// lazy: extra 极其懒惰
public void fun7() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- String hql = "from Customer"; Query query = session.createQuery(hql); List<Customer> list = query.list(); for (Customer c : list) {
System.out.println(c);
System.out.println(c.getLinkMens().size());
System.out.println(c.getLinkMens());
} // ----------------------------------------------------
tx.commit();
session.close(); }

SQL:

Hibernate:
select
customer0_.cust_id as cust_id1_0_,
customer0_.cust_name as cust_nam2_0_,
customer0_.cust_source as cust_sou3_0_,
customer0_.cust_industry as cust_ind4_0_,
customer0_.cust_level as cust_lev5_0_,
customer0_.cust_linkman as cust_lin6_0_,
customer0_.cust_phone as cust_pho7_0_,
customer0_.cust_mobile as cust_mob8_0_
from
cst_customer customer0_
Customer [cust_id=7, cust_name=测试名称1]
Hibernate:
select
linkmens0_.lkm_cust_id as lkm_cus10_1_1_,
linkmens0_.lkm_id as lkm_id1_1_1_,
linkmens0_.lkm_id as lkm_id1_1_0_,
linkmens0_.lkm_gender as lkm_gend2_1_0_,
linkmens0_.lkm_name as lkm_name3_1_0_,
linkmens0_.lkm_phone as lkm_phon4_1_0_,
linkmens0_.lkm_email as lkm_emai5_1_0_,
linkmens0_.lkm_qq as lkm_qq6_1_0_,
linkmens0_.lkm_mobile as lkm_mobi7_1_0_,
linkmens0_.lkm_memo as lkm_memo8_1_0_,
linkmens0_.lkm_position as lkm_posi9_1_0_,
linkmens0_.lkm_cust_id as lkm_cus10_1_0_
from
cst_linkman linkmens0_
where
linkmens0_.lkm_cust_id in (
select
customer0_.cust_id
from
cst_customer customer0_
)

2.关联属性懒加载(先查询联系人,跟据联系人反查顾客)

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="cn.qlq.domain" >
<class name="LinkMan" table="cst_linkman" >
<id name="lkm_id" >
<generator class="native"></generator>
</id>
<property name="lkm_gender" ></property>
<property name="lkm_name" ></property>
<property name="lkm_phone" ></property>
<property name="lkm_email" ></property>
<property name="lkm_qq" ></property>
<property name="lkm_mobile" ></property>
<property name="lkm_memo" ></property>
<property name="lkm_position" ></property>
<!--
fetch 决定加载的sql语句
select: 使用单表查询
join : 多表查询 (会导致lazy失效)
lazy 决定加载时机
false: 立即加载
proxy: 由customer的类级别加载策略决定.
-->
<many-to-one name="customer" column="lkm_cust_id" class="Customer" fetch="select" lazy="proxy"></many-to-one>
</class>
</hibernate-mapping>

1.fetch为select,lazy为proxy,Customer类的lazy为true

测试代码:

    // 集合级别的关联
// fetch:select 单表查询
// lazy:proxy 代理,也就是由Customer的lazy属性决定是否懒加载
//Customer的lazy为true
@Test
public void fun1() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- LinkMan linkMan = session.get(LinkMan.class, 5l);
System.out.println("-------1------------");
Customer customer = linkMan.getCustomer();
System.out.println("-------2------------");
System.out.println(customer);// 打印SQL // ----------------------------------------------------
tx.commit();
session.close(); }

SQL:

Hibernate:
select
linkman0_.lkm_id as lkm_id1_1_0_,
linkman0_.lkm_gender as lkm_gend2_1_0_,
linkman0_.lkm_name as lkm_name3_1_0_,
linkman0_.lkm_phone as lkm_phon4_1_0_,
linkman0_.lkm_email as lkm_emai5_1_0_,
linkman0_.lkm_qq as lkm_qq6_1_0_,
linkman0_.lkm_mobile as lkm_mobi7_1_0_,
linkman0_.lkm_memo as lkm_memo8_1_0_,
linkman0_.lkm_position as lkm_posi9_1_0_,
linkman0_.lkm_cust_id as lkm_cus10_1_0_
from
cst_linkman linkman0_
where
linkman0_.lkm_id=?
-------1------------
-------2------------
Hibernate:
select
customer0_.cust_id as cust_id1_0_0_,
customer0_.cust_name as cust_nam2_0_0_,
customer0_.cust_source as cust_sou3_0_0_,
customer0_.cust_industry as cust_ind4_0_0_,
customer0_.cust_level as cust_lev5_0_0_,
customer0_.cust_linkman as cust_lin6_0_0_,
customer0_.cust_phone as cust_pho7_0_0_,
customer0_.cust_mobile as cust_mob8_0_0_
from
cst_customer customer0_
where
customer0_.cust_id=?
Customer [cust_id=9, cust_name=测试名称3]

2.fetch为select,lazy为proxy,Customer类的lazy为false

测试代码:

    // 集合级别的关联
// fetch:select 单表查询
// lazy:proxy 代理,也就是由Customer的lazy属性决定是否懒加载
//Customer的lazy为false
@Test
public void fun2() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- LinkMan linkMan = session.get(LinkMan.class, 5l);
System.out.println("-------1------------");
Customer customer = linkMan.getCustomer();
System.out.println("-------2------------");
System.out.println(customer);// 打印SQL // ----------------------------------------------------
tx.commit();
session.close(); }

SQL:

Hibernate:
select
linkman0_.lkm_id as lkm_id1_1_0_,
linkman0_.lkm_gender as lkm_gend2_1_0_,
linkman0_.lkm_name as lkm_name3_1_0_,
linkman0_.lkm_phone as lkm_phon4_1_0_,
linkman0_.lkm_email as lkm_emai5_1_0_,
linkman0_.lkm_qq as lkm_qq6_1_0_,
linkman0_.lkm_mobile as lkm_mobi7_1_0_,
linkman0_.lkm_memo as lkm_memo8_1_0_,
linkman0_.lkm_position as lkm_posi9_1_0_,
linkman0_.lkm_cust_id as lkm_cus10_1_0_
from
cst_linkman linkman0_
where
linkman0_.lkm_id=?
Hibernate:
select
customer0_.cust_id as cust_id1_0_0_,
customer0_.cust_name as cust_nam2_0_0_,
customer0_.cust_source as cust_sou3_0_0_,
customer0_.cust_industry as cust_ind4_0_0_,
customer0_.cust_level as cust_lev5_0_0_,
customer0_.cust_linkman as cust_lin6_0_0_,
customer0_.cust_phone as cust_pho7_0_0_,
customer0_.cust_mobile as cust_mob8_0_0_
from
cst_customer customer0_
where
customer0_.cust_id=?
-------1------------
-------2------------
Customer [cust_id=9, cust_name=测试名称3]

3.fetch为join,lazy属性失效

代码:

    // 集合级别的关联
// join 单表查询
// lazy: 属性失效
@Test
public void fun3() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- LinkMan linkMan = session.get(LinkMan.class, 5l);
System.out.println("-------1------------");
Customer customer = linkMan.getCustomer();
System.out.println("-------2------------");
System.out.println(customer);// 打印SQL // ----------------------------------------------------
tx.commit();
session.close(); }

SQL:

Hibernate:
select
linkman0_.lkm_id as lkm_id1_1_0_,
linkman0_.lkm_gender as lkm_gend2_1_0_,
linkman0_.lkm_name as lkm_name3_1_0_,
linkman0_.lkm_phone as lkm_phon4_1_0_,
linkman0_.lkm_email as lkm_emai5_1_0_,
linkman0_.lkm_qq as lkm_qq6_1_0_,
linkman0_.lkm_mobile as lkm_mobi7_1_0_,
linkman0_.lkm_memo as lkm_memo8_1_0_,
linkman0_.lkm_position as lkm_posi9_1_0_,
linkman0_.lkm_cust_id as lkm_cus10_1_0_,
customer1_.cust_id as cust_id1_0_1_,
customer1_.cust_name as cust_nam2_0_1_,
customer1_.cust_source as cust_sou3_0_1_,
customer1_.cust_industry as cust_ind4_0_1_,
customer1_.cust_level as cust_lev5_0_1_,
customer1_.cust_linkman as cust_lin6_0_1_,
customer1_.cust_phone as cust_pho7_0_1_,
customer1_.cust_mobile as cust_mob8_0_1_
from
cst_linkman linkman0_
left outer join
cst_customer customer1_
on linkman0_.lkm_cust_id=customer1_.cust_id
where
linkman0_.lkm_id=?
-------1------------
-------2------------
Customer [cust_id=9, cust_name=测试名称3]

总结:

  为了提高效率.fetch的选择上应选择select. lazy的取值应选择 true. 全部使用默认值.

3.批量抓取策略(batch-size属性)

  此次略用于获取客户联系人的时候,一次抓取几个客户的联系人。此策略用于避免多次访问数据库,没有此策略是一次获取一个客户联系人,有了此策略可以一次获取多个客户的,减少访问数据库次数。

例如

<?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="cn.qlq.domain" >
<class name="Customer" table="cst_customer">
<id name="cust_id" >
<generator class="native"></generator>
</id>
<property name="cust_name" column="cust_name" >
</property>
<property name="cust_source" column="cust_source" ></property>
<property name="cust_industry" column="cust_industry" ></property>
<property name="cust_level" column="cust_level" ></property>
<property name="cust_linkman" column="cust_linkman" ></property>
<property name="cust_phone" column="cust_phone" ></property>
<property name="cust_mobile" column="cust_mobile" ></property> <!--
lazy属性: 决定是否延迟加载
true(默认值): 延迟加载,懒加载
false: 立即加载
extra: 极其懒惰
fetch属性: 决定加载策略.使用什么类型的sql语句加载集合数据
select(默认值): 单表查询加载
join: 使用多表查询加载集合
subselect:使用子查询加载集合
-->
<!-- batch-size: 5 抓取集合的数量为5.
抓取客户的集合时,一次抓取几个客户的联系人集合.
-->
<set name="linkMens" batch-size="5">
<key column="lkm_cust_id" ></key>
<one-to-many class="LinkMan" />
</set>
</class>
</hibernate-mapping>

测试代码:

    public void fun5() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ---------------------------------------------------- String hql = "from Customer"; Query query = session.createQuery(hql); List<Customer> list = query.list(); for (Customer c : list) {
System.out.println(c.getLinkMens());
} // ----------------------------------------------------
tx.commit();
session.close(); }

SQL:

Hibernate:
select
customer0_.cust_id as cust_id1_0_,
customer0_.cust_name as cust_nam2_0_,
customer0_.cust_source as cust_sou3_0_,
customer0_.cust_industry as cust_ind4_0_,
customer0_.cust_level as cust_lev5_0_,
customer0_.cust_linkman as cust_lin6_0_,
customer0_.cust_phone as cust_pho7_0_,
customer0_.cust_mobile as cust_mob8_0_
from
cst_customer customer0_
Hibernate:
select
linkmens0_.lkm_cust_id as lkm_cus10_1_1_,
linkmens0_.lkm_id as lkm_id1_1_1_,
linkmens0_.lkm_id as lkm_id1_1_0_,
linkmens0_.lkm_gender as lkm_gend2_1_0_,
linkmens0_.lkm_name as lkm_name3_1_0_,
linkmens0_.lkm_phone as lkm_phon4_1_0_,
linkmens0_.lkm_email as lkm_emai5_1_0_,
linkmens0_.lkm_qq as lkm_qq6_1_0_,
linkmens0_.lkm_mobile as lkm_mobi7_1_0_,
linkmens0_.lkm_memo as lkm_memo8_1_0_,
linkmens0_.lkm_position as lkm_posi9_1_0_,
linkmens0_.lkm_cust_id as lkm_cus10_1_0_
from
cst_linkman linkmens0_
where
linkmens0_.lkm_cust_id in (
?, ?, ?, ?, ?
)
[LinkMan [lkm_id=4, lkm_gender=null, lkm_name=田七, lkm_phone=null, lkm_email=null, lkm_qq=null, lkm_mobile=null, lkm_memo=null, lkm_position=null, customer=Customer [cust_id=7, cust_name=测试名称1]], LinkMan [lkm_id=3, lkm_gender=null, lkm_name=王八, lkm_phone=null, lkm_email=null, lkm_qq=null, lkm_mobile=null, lkm_memo=null, lkm_position=null, customer=Customer [cust_id=7, cust_name=测试名称1]]]
[]
[LinkMan [lkm_id=5, lkm_gender=null, lkm_name=99, lkm_phone=null, lkm_email=null, lkm_qq=null, lkm_mobile=null, lkm_memo=null, lkm_position=null, customer=Customer [cust_id=9, cust_name=测试名称3]]]
[]
[]
Hibernate:
select
linkmens0_.lkm_cust_id as lkm_cus10_1_1_,
linkmens0_.lkm_id as lkm_id1_1_1_,
linkmens0_.lkm_id as lkm_id1_1_0_,
linkmens0_.lkm_gender as lkm_gend2_1_0_,
linkmens0_.lkm_name as lkm_name3_1_0_,
linkmens0_.lkm_phone as lkm_phon4_1_0_,
linkmens0_.lkm_email as lkm_emai5_1_0_,
linkmens0_.lkm_qq as lkm_qq6_1_0_,
linkmens0_.lkm_mobile as lkm_mobi7_1_0_,
linkmens0_.lkm_memo as lkm_memo8_1_0_,
linkmens0_.lkm_position as lkm_posi9_1_0_,
linkmens0_.lkm_cust_id as lkm_cus10_1_0_
from
cst_linkman linkmens0_
where
linkmens0_.lkm_cust_id in (
?, ?, ?
)

  通过SQL看出获取客户联系人的时候一次获取5个客户的联系人,最后一次由于没有五个客户所以会查询剩余3个客户的联系人。

问题:   no-session问题解决: 扩大session的作用范围.

  在懒加载的策略中,我们通常是在Service层打开事务、session,service代码执行完毕只会进行提交或者回滚。但是我们的对象(代理对象)经常放在request域中带到页面进行显示,也就是到了页面才使用对象(查询数据库),此时session已经关闭,如果使用了懒加载策略会报no-session异常。解决办法:过滤器扩大session作用范围(filter可以在请求执行前后都执行一些代码),如下图逻辑:

  其实SSH整合的时候spring已经做了过滤器来实现此功能,会在搭建SSH环境的时候介绍。

Hibernate延迟加载策略的更多相关文章

  1. Hibernnate延迟加载策略(这么详细你还看不懂)

    好久没有认真写过博客了,今天就好好的写一篇吧!!!!!!!!! 当Hibernate 从数据库中加载某个对象(例如:Dept对象)时,如果同时自动加载所有的关联的某个对象(例如:Emp对象),而程序实 ...

  2. Hibernate 延迟加载

    一.什么是延迟加载? 延迟加载是指当应用程序想要从数据库获取对象时(在没有设置lazy属性值为false),Hibernate只是从数据库获取符合条件的对象的OId从而生成代理对象,并没有加载出对象访 ...

  3. [原创]java WEB学习笔记88:Hibernate学习之路-- -Hibernate检索策略(立即检索,延迟检索,迫切左外连接检索)

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  4. Hibernate检索策略

    1. Hibernate的检索策略概述: 检索数据时的 2 个问题:    1.不浪费内存:当 Hibernate 从数据库中加载 Customer 对象时, 如果同时加载所有关联的 Order 对象 ...

  5. 【转】hibernate 延迟加载

    Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认也会被延迟加载.hibernate 通过这种延迟加载来降低系统的内存开销,从而保证 Hiberna ...

  6. Hibernate优化策略

    https://blog.csdn.net/blueheart20/article/details/21019043 https://blog.csdn.net/yerenyuan_pku/artic ...

  7. hibernate 延迟加载深入分析(persistentSet的延迟加载)

    Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认也会被延迟加载.Hibernate 通过这种延迟加载来降低系统的内存开销,从而保证 Hiberna ...

  8. Hibernate 延迟加载 分析

    出处:http://www.ibm.com/developerworks/cn/java/j-lo-hibernatelazy/#icomments Hibernate 的延迟加载(lazy load ...

  9. Hibernate检索策略与检索方式

    hibernate的Session在加载Java对象时,一般都会把鱼这个对象相关联的其他Java对象也都加载到缓存中,以方便程序的调用.但很多情况下,我们不需要加载太多无用的对象到缓存中,一来会占用大 ...

随机推荐

  1. 铁大快捷记账Alpha版使用说明书

    一. 引言 (1) 编写目的 (2) 参考资料 (3) 术语和缩写词 二. 网站概述 (1) 网站用途 (2) 网站运行 三. 网站使用过程 (1)网站登录 (2) 功能说明 一.引言 (1)编写目的 ...

  2. @PathVariable获取带点参数,获取不全

    {account:.+}在{account}后加上:.+ 可参考原博:http://blog.csdn.net/jrainbow/article/details/46126179

  3. c++中队列queue和栈stack的基本操作

    1.queue 模板类的定义在<queue>头文件中. 定义queue 对象的示例代码如下:queue<int> q1;queue<double> q2; queu ...

  4. 使用redis防止抢购商品超卖

    前言: redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用. 本篇博文用来测试下使用redis来防止抢购商品超卖问题. 内容: 使用redis的list进行测试 思路是设置一个 ...

  5. Python日志模块简单使用

    def loginfo(info): # create logger logger = logging.getLogger('[cpu and mem]**********') # Set defau ...

  6. Delphi实现DBGrid全选和反选功能

    Delphi实现Dbgrid全选和反选.清除全选的功能,不管是在Delphi下,还是在WEB开发中,这种功能都是很实用的,是进行数据批量操作的基础.本模块就是实现了为Delphi的DBGrid数据列表 ...

  7. DELPHI动态创建窗体

    //第一种方式 procedure TForm1.btn1Click(Sender: TObject); begin With TForm2.Create(Application) do Try Sh ...

  8. 初征——NOIP2018游记

    前言 从最初接触oi到今年noip到来,也已经将近有一年了.从对于程序一窍不懂到现在开始学习算法,只是短短的不到一年的时间罢了.这次noip,不仅仅是我oi生涯的第一次noip,更是相当于是对我这一年 ...

  9. BZOJ2741 FOTILE模拟赛L(分块+可持久化trie)

    显然做个前缀和之后变成询问区间内两个数异或最大值. 一种暴力做法是建好可持久化trie后直接枚举其中一个数查询,复杂度O(nmlogv). 观察到数据范围很微妙.考虑瞎分块. 设f[i][j]为第i个 ...

  10. P4932 浏览器

    题目背景 __stdcall在用Edge玩slay的时候,鼠标会经常失灵,这让她十分痛苦,因此她决定也要让你们感受一下Edge制造的痛苦. 题目描述 __stdcall给了你n个点,第i个点有权值x[ ...