hibernate抓取策略(关联级别的延迟加载)

1.3Hibernate的抓取策略(优化)

延迟加载的概述
通过一个对象抓取到关联对象需要发送SQL语句,SQL语句如何发送,发送成什么样格式通过策略进行配置。
通过或者在上通过fetch属性进行设置
fetch和这些标签上的lazy如何设置优化发送的SQL语句
1.3.1.1什么是延迟加载
延迟加载:lazy(懒加载)。执行到该行代码的时候,不会发送语句去进行查询,在真正使用这个对象的属性的时候才会发送SQL语句进行查询。
1.3.1.2延迟加载的分类

  1. 类级别的延迟加载

指的是通过load方法查询某个对象的时候,是否采用延迟。session.load(Customer.class,1l);
类级别延迟加载通过上的lazy进行配置,如果让lazy失效
将lazy设置为false
将持久化类使用final修饰
Hibernate. Initialize() 立即加载

  1. 关联级别的延迟加载(重点

指的是在查询到某个对象的时候,查询其关联的对象的时候,是否采用延迟加载。
Customer customer = session.get(Customer.class,1l);
customer.getLinkMans();
----通过客户获得联系人的时候,联系人对象是否采用了延迟加载,称为是关联级别的延迟。
抓取策略往往会和关联级别的延迟加载一起使用,优化语句。
抓取策略
1.3.2.1抓取策略的概述
通过一个对象抓取到关联对象需要发送SQL语句,SQL语句如何发送,发送成什么样格式通过策略进行配置。
通过或者上通过fetch属性进行设置
fetch和这些标签上的lazy如何设置优化发送的SQL语句

fetch和lazy

fetch:抓取策略,控制SQL语句样式,可选的值如下
select :默认值,发送普通的select语句,查询关联对象
join :发送一条迫切左外连接查询关联对象
当选择这个属性时,只有一种情况,不存在1*3 三种
subselect :发送一条子查询查询其关联对象
效率很慢,能用多表查询尽量用 多表查询
lazy:延迟加载,控制查询关联对象的时候是否采用延迟,可选的值如下
(控制发送的时机)
true :默认值,查询关联对象的时候,采用延迟加载
false :查询关联对象的时候,不采用延迟加载
extra :及其懒惰。

在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join。

配置代码:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
        
<hibernate-mapping>
	<class name="com.yidongxueyuan.domain.Customer" table="cst_customer" lazy="false" >
	
		<id name="cust_id" column="cust_id"  >
			<generator class="native"/>
		</id>
		<property name="cust_name" column="cust_name" length="21" type="string" not-null="true" unique="false"/>
		<property name="cust_source" column="cust_source"/>
		<property name="cust_industry" column="cust_industry"/>
		<property name="cust_level" column="cust_level"/>
		<property name="cust_phone" column="cust_phone"/>
		<property name="cust_mobile" column="cust_mobile"/>
		
		<!-- 
		   set: 标签: 
		    name:方的该实体类当中属性的名称, 属性的类型是一个set集合类型: 
		    save-update:表明可以进行级联操作: 
		        就是在操作Customer对象的时候, 可以同时操作Customer关联的其他的对象。
		 -->
		 <set  name="linkMans"  cascade="save-update" inverse="true" batch-size="10">
		 	
		 	<!-- 
		 	 多的一方,外键的名称: 
		 	 -->
		 	<key column="lkm_cust_id"/>
		 	<!-- 
		 	    one-to-many :  
		 	    表明表和表之间的关系:  一对多: 
		 	    class: 放3的是多的一方的全路径名称。 
		 	 -->
		 	<one-to-many class="com.yidongxueyuan.domain.LinkedMan" />
		 </set>
		
	</class>
	
</hibernate-mapping>        

many-to-one 上的fetch和lazy

fetch (只有两种):抓取策略,控制SQL语句格式。
select :默认值,发送普通的select语句,查询关联对象。
join :发送一条迫切左外连接。
lazy :延迟加载,控制查询关联对象的时候是否采用延迟。
proxy :默认值,proxy具体的取值,取决于另一端的上的lazy的值。
1 理解为 true:

false :查询关联对象,不采用延迟。
no-proxy :(不会使用)
在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join。

批量抓取

什么是批量抓取
在抓取的策略中有一种叫做批量抓取,就是同时查询多个对象的关联对象的时候, 可以采用批量抓取进行优化。当然这个不是特别重要。
如果要实现批量的抓取效果,可以通过配置batch-size来完成。
1.3.3.2测试批量抓取
【查询客户批量抓取练习人】
@SuppressWarnings(“unchecked”)
@Test
public void FetchDemo4() throws Exception {
/*
* 查询客户, 客户关联的联系人是否查询:
* 在Customer.hbm.xml中 集合上配置batch-size=“4”;
*
*/
//获得链接对象:
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();

	//查询客户: 客户关联的联系人: 
	List<Customer> list = session.createQuery("from Customer").list();
	
	for(Customer customer: list){
		//打印客户的名称: 
		System.out.println("客户的名称:"+customer.getCust_name());
		//查询客户关联的联系人: 
		for(LinkMan linkman :customer.getLinkMans()){
			System.out.println("客户对应的联系人的名称:"+linkman.getLkm_name());
		}
	}
	tx.commit();
}

在没有设置batch-size之前运行以上代码,会出现如下的效果:

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_phone as cust_pho6_0_,
customer0_.cust_mobile as cust_mob7_0_
from
cst_customer customer0_ 客户的名称:何老师 Hibernate:
select
linkmans0_.lkm_cust_id as lkm_cus10_1_0_,
linkmans0_.lkm_id as lkm_id1_1_0_,
linkmans0_.lkm_id as lkm_id1_1_1_,
linkmans0_.lkm_name as lkm_name2_1_1_,
linkmans0_.lkm_gender as lkm_gend3_1_1_,
linkmans0_.lkm_phone as lkm_phon4_1_1_,
linkmans0_.lkm_mobile as lkm_mobi5_1_1_,
linkmans0_.lkm_email as lkm_emai6_1_1_,
linkmans0_.lkm_qq as lkm_qq7_1_1_,
linkmans0_.lkm_position as lkm_posi8_1_1_,
linkmans0_.lkm_memo as lkm_memo9_1_1_,
linkmans0_.lkm_cust_id as lkm_cus10_1_1_
from
cst_linkman linkmans0_
where
linkmans0_.lkm_cust_id=? 客户对应的联系人的名称:翠花3 客户对应的联系人的名称:翠花6 客户的名称:毕老师 Hibernate:
select
linkmans0_.lkm_cust_id as lkm_cus10_1_0_,
linkmans0_.lkm_id as lkm_id1_1_0_,
linkmans0_.lkm_id as lkm_id1_1_1_,
linkmans0_.lkm_name as lkm_name2_1_1_,
linkmans0_.lkm_gender as lkm_gend3_1_1_,
linkmans0_.lkm_phone as lkm_phon4_1_1_,
linkmans0_.lkm_mobile as lkm_mobi5_1_1_,
linkmans0_.lkm_email as lkm_emai6_1_1_,
linkmans0_.lkm_qq as lkm_qq7_1_1_,
linkmans0_.lkm_position as lkm_posi8_1_1_,
linkmans0_.lkm_memo as lkm_memo9_1_1_,
linkmans0_.lkm_cust_id as lkm_cus10_1_1_
from
cst_linkman linkmans0_
where
linkmans0_.lkm_cust_id=?

客户对应的联系人的名称:凤姐花5
客户对应的联系人的名称:凤姐花3
客户的名称:王八蛋3
Hibernate:
select
linkmans0_.lkm_cust_id as lkm_cus10_1_0_,
linkmans0_.lkm_id as lkm_id1_1_0_,
linkmans0_.lkm_id as lkm_id1_1_1_,
linkmans0_.lkm_name as lkm_name2_1_1_,
linkmans0_.lkm_gender as lkm_gend3_1_1_,
linkmans0_.lkm_phone as lkm_phon4_1_1_,
linkmans0_.lkm_mobile as lkm_mobi5_1_1_,
linkmans0_.lkm_email as lkm_emai6_1_1_,
linkmans0_.lkm_qq as lkm_qq7_1_1_,
linkmans0_.lkm_position as lkm_posi8_1_1_,
linkmans0_.lkm_memo as lkm_memo9_1_1_,
linkmans0_.lkm_cust_id as lkm_cus10_1_1_
from
cst_linkman linkmans0_
where
linkmans0_.lkm_cust_id=?
客户对应的联系人的名称:蛋网吧3
查询结果分析: 目前数据库中有三个用户, 那么会发现执行代码会发生三条sql语句。我们想能不能发送一条SQL直接将两个客户的关联的联系人一起查询出来呢? 此时我们可以在标签上设置batch-size实现优化的效果。

实现配置如下:Customer.hbm.xml当中的set标签上设置:

配置后运行,发送的sql语句如下:

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_phone as cust_pho6_0_,
        customer0_.cust_mobile as cust_mob7_0_ 
    from
        cst_customer customer0_
客户的名称:何老师
Hibernate: 
    select
        linkmans0_.lkm_cust_id as lkm_cus10_1_1_,
        linkmans0_.lkm_id as lkm_id1_1_1_,
        linkmans0_.lkm_id as lkm_id1_1_0_,
        linkmans0_.lkm_name as lkm_name2_1_0_,
        linkmans0_.lkm_gender as lkm_gend3_1_0_,
        linkmans0_.lkm_phone as lkm_phon4_1_0_,
        linkmans0_.lkm_mobile as lkm_mobi5_1_0_,
        linkmans0_.lkm_email as lkm_emai6_1_0_,
        linkmans0_.lkm_qq as lkm_qq7_1_0_,
        linkmans0_.lkm_position as lkm_posi8_1_0_,
        linkmans0_.lkm_memo as lkm_memo9_1_0_,
        linkmans0_.lkm_cust_id as lkm_cus10_1_0_ 
    from
        cst_linkman linkmans0_ 
    where
        linkmans0_.lkm_cust_id in (
            ?, ?, ?
        )

客户对应的联系人的名称:翠花2
客户对应的联系人的名称:翠花4
客户的名称:毕老师
客户对应的联系人的名称:凤姐花2
客户对应的联系人的名称:凤姐花6
客户的名称:王八蛋3
客户对应的联系人的名称:蛋网吧3
分析运行的sql语句: 发送的sql语句发生了变化,当数据量越大的时候, 效果越是明显。这是在查询所有的客户的时候批量抓取联系人。那么如果我们要实现查询多个联系人的时候,抓取联系人对应的客户呢? 同样需要设置batch-size。但是不是在上设置, 还是在客户的一端的 上设置即可。
【查询联系人批量抓取客户】
@SuppressWarnings(“unchecked”)
@Test
public void FetchDemo5() throws Exception {
/*
* 查询联系人,批量抓取客户
* 在Customer.hbm.xml中
* 注意: 如果在查询的过程当中出现了NullPointerException: 说明联系人的外键是null,没有关联的用户信息。
*/
//获得链接对象:
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();

	//查询联系人信息: 
	List<LinkMan> list = session.createQuery("from LinkMan").list();
	
	//遍历联系人信息: 
	for(LinkMan linkMan : list){
		System.out.println(linkMan.getLkm_name());
		//打印联系人对应的客户的名称
		System.out.println(linkMan.getCustomer().getCust_name());
	}
	
	tx.commit();
}

运行的结果分析:

 select
        linkman0_.lkm_id as lkm_id1_1_,
        linkman0_.lkm_name as lkm_name2_1_,
        linkman0_.lkm_gender as lkm_gend3_1_,
        linkman0_.lkm_phone as lkm_phon4_1_,
        linkman0_.lkm_mobile as lkm_mobi5_1_,
        linkman0_.lkm_email as lkm_emai6_1_,
        linkman0_.lkm_qq as lkm_qq7_1_,
        linkman0_.lkm_position as lkm_posi8_1_,
        linkman0_.lkm_memo as lkm_memo9_1_,
        linkman0_.lkm_cust_id as lkm_cus10_1_ 
    from
        cst_linkman linkman0_
翠花0
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_phone as cust_pho6_0_0_,
        customer0_.cust_mobile as cust_mob7_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_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_phone as cust_pho6_0_0_,
        customer0_.cust_mobile as cust_mob7_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_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_phone as cust_pho6_0_0_,
        customer0_.cust_mobile as cust_mob7_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?
王八蛋3
蛋网吧2
王八蛋3
配置批量抓取:

运行结果如下: 
    select
        linkman0_.lkm_id as lkm_id1_1_,
        linkman0_.lkm_name as lkm_name2_1_,
        linkman0_.lkm_gender as lkm_gend3_1_,
        linkman0_.lkm_phone as lkm_phon4_1_,
        linkman0_.lkm_mobile as lkm_mobi5_1_,
        linkman0_.lkm_email as lkm_emai6_1_,
        linkman0_.lkm_qq as lkm_qq7_1_,
        linkman0_.lkm_position as lkm_posi8_1_,
        linkman0_.lkm_memo as lkm_memo9_1_,
        linkman0_.lkm_cust_id as lkm_cus10_1_ 
    from
        cst_linkman linkman0_
翠花0
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_phone as cust_pho6_0_0_,
        customer0_.cust_mobile as cust_mob7_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id in (
            ?, ?, ?
        )

分析结果: 发送的语句和之前发生了变化, 这些优化都是Hibernate提升自身性能的手段。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方-教育技术博主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值