Hibernate学习笔记12,抓取策略,客户查询的优化

一、Hibernate抓取策略

Hibernate抓取策略是指当应用程序需要在关联关系间进行导航的时候,Hibernate如何获取关联对象的策略。

Hibernate有如下几种抓取策略:

1、链接抓取(Join fetching):Hibernate 通过在select语句中使用out join来获取对象的关联实例或者关联集合。

2、查询抓取(Select fetching):发送另外一条select语句抓取当前对象的关联实体或者关联集合。除非我们显示地指定lazy=”false”禁止延迟抓取,否则只有当我们真正访问了关联关系的时候才会执行第二条select语句。

3、子查询抓取:另外发送一条SELECT 语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy=”false” 禁止延迟抓取(lazyfetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。

4、批量抓取(Batch fetching) - 对查询抓取的优化方案, 通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合。

Hibernate会区分下列各种情况:

  • Immediate fetching,立即抓取 - 当宿主被加载时,关联、集合或属性被立即抓取。

  • Lazy collectionfetching,延迟集合抓取- 直到应用程序对集合进行了一次操作时,集合才被抓取。(对集合而言这是默认行为。)

  • “Extra-lazy”collection fetching,”Extra-lazy”集合抓取 -对集合类中的每个元素而言,都是直到需要时才去访问数据库。除非绝对必要,Hibernate不会试图去把整个集合都抓取到内存里来(适用于非常大的集合)。

  • Proxy fetching,代理抓取 - 对返回单值的关联而言,当其某个方法被调用,而非对其关键字进行get操作时才抓取。

  • “No-proxy”fetching,非代理抓取 - 对返回单值的关联而言,当实例变量被访问的时候进行抓取。与上面的代理抓取相比,这种方法没有那么“延迟”得厉害(就算只访问标识符,也会导致关联抓取)但是更加透明,因为对应用程序来说,不再看到proxy。这种方法需要在编译期间进行字节码增强操作,因此很少需要用到。

  • Lazy attributefetching,属性延迟加载 - 对属性或返回单值的关联而言,当其实例变量被访问的时候进行抓取。需要编译期字节码强化,因此这一方法很少是必要的。

二、选择合理的抓取策略

定制合理的抓取策略对系统的提升有很大的作用。

查询抓取在N+1查询的情况下是极其脆弱的,因此我们可能会要求在映射文件中定义连接抓取(fetch=”join”)。

但是在映射文件中定义的抓取策略将会产生以下影响:通过get()或者load()方法获取数据。。只有在关联之间进行导航时,才会隐式的取得数据。

条件查询,使用了subselect抓取的HQL查询

不管使用哪种抓取策略,定义为非延时的类图会保证一定装载入内存,这就意味着一条HQL查询后紧跟着一系列的查询。

所以我们一般是这样做:通常情况下,我们并不使用映射文件进行抓取策略的定制,更多的是,保持其默认值然后在待定事物中,适用HQL的左连接对其进行重载。

Hibernate推荐的做法也是最佳实践:把所有对象关联的抓取都设为lazy!然后在特定事务中进行重载。

这种考虑是基于:对象之间的关联式错综复杂的,有时候哪怕我们只是一个简单的load,也会导致很多对象被load出来!所以在Hibernate中,所有对象关联都是lazy的。

四、Hibernate的批量抓取

在Hibernate中,对于关联抓取,可以定义每次抓取数据的数量。批量地将数据载入内存,减少与数据库交互的次数。在应用程序中可以定义默认的关联抓取数量。

Hibernate提供了两种批量抓取方案:类级别和集合级别。

类级别的批量查询。如果一个Session中需要载入30个student实例,在student中拥有一个成员变量class,该class执行Class对象。如果lazy=“true”,如果们需要变量整个student集合,每一个student都需要getClass(),hibernate在默认情况下回执行30次select查询语句,得到Class对象。这个时候可以通过在映射文件的Class属性,batch-size。

<class name=”Class” batch-size=”15”>….</class>  

这样Hibernate将只需要执行两次查询即可:15,15。

集合级别的批量查询。如果我们需要遍历Class所拥有的所有Student对象,在Session中需要载入30个Class对象,遍历Class集合将会引起30次Select查询,每次查询都会调用getStudents()。如果在Class的映射定义中,允许对Students进行批量抓取,则Hibernate就会预先加载整个集合。

<set name=”students” batch-size=”15”></set>  

以上内容转自这里


基于学习内容对客户查询进行优化

当查询客户列表时候,根据主键id查询base_dict的sql语句在控制台打印了多次。
这里写图片描述
原因:
通过对象导航,每条记录调用get方法,发出sql。
需要优化一下,查询客户信息 只发出一条sql,查询客户来源时候不再发出sql。

类级别的抓取策略

1、延迟加载
在hbm.xml中class标签内设置lazy=”true”(延迟加载),相当于load方法

2、立即加载
在hbm.xml中class标签内设置lazy=”false”,立即加载,load和get方法效果一样。

关联级别的抓取策略(重点掌握)
一对多、多对多

元素提供 lazy属性 和 fetch 用于设置 抓取策略

fetch默认select,lazy默认为true:fetch=”select”每get请求发出sql,lazy=true表示延迟加载

fetch=”join”(lazy不起作用):批量抓取,自动生成左外连接语句,将关联的多方数据抓取到一方的属性中。

最佳实践:
在进行一对多、多对多查询时候,只查询基本时候一般不需要关联多方数据的,此采用延迟加载的抓取策略。

多对一

根据客户查询客户来源,多对一。

hbm采用 元素,提供lazy属性和fetch属性,用来配置抓取策略

fetch=”join”:自动生成左外连接,将关联一方属性对象抓取到多方的属性,查询客户信息,将many-to-one中fetch设置join,通过qbc查询客户时自动生成一个客户表和数据字典表的关联查询语句。

fetch=select,lazy=”true”:延迟加载

如果lazy设置为proxy,根据对象的class标签设置类级别抓取策略有关。
对方如果是lazy=true,就是延迟加载,如果对方设置lazy=false,立即加载。

实现

1、当查询客户列表时候,关联查询客户来源信息。
分析:查询客户需要立即查询客户来源信息,此时不采用延迟加载,立即加载,将数据批量抓取到,存在客户对象。
CstCustomer.hbm.xml中many-to-one设置fetch=”join”
这里写图片描述
2、当查询客户列表的时候,不需要立即关联查询客户下的联系人
分析:第一时间不需要查询出关联的多方即联系人,采用延迟加载
这里写图片描述


总结

抓取策略(重要理解,会用)
包括:
1)延迟加载
lazy=’true’延迟加载,lazy=false立即加载
2)立即加载
通过对象的属性将数据立即加载出来,设置到当前对象中。
比如:查询客户关联查询客户来源
在查询客户时候立即将客户来源也查询出来,将客户来源信息设置客户对象的属性中。
fetch=”select” :一条一条的查询,一般设置fetch=”select” ,lazy=true :延迟加载
fetch=”join”:lazy失效 将当前对象和关联对象自动拼接成一个左外连接sql,将关联的数据一次全部查询 出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值