文档章节

Hibernate的抓取策略

猪刚烈
 猪刚烈
发布于 2014/10/12 11:40
字数 1383
阅读 12
收藏 0

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

Hibernate推荐的原则是:通常情况下,我们并不使用映射文档进行抓取策略的定制。更多的是,保持其默认值,然后在特
定的事务中, 使用 HQL 的左连接抓取(left join fetch) 对其进行重载。

 

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

 这种考虑是基于:对象图是错综复杂的,有时候哪怕我们只是eager load了一个对象也可能会导致很多对象被load出来!

在Hibernate中,所有对象关联都是lazy的,但是JPA有所不同,one-to-one和many-to-one对象的默认抓取策略是eager!因此在使用JPA @annotation时务必要把这些默认是eager的映射都改成lazy!

以下摘自JPwH一书571页:

in Hibernate:
the associated entity instance must be fetched eagerly, not lazily. We already mentioned that Java Persistence has a different default fetch plan than Hibernate. Although all associations in Hibernate are completely lazy, all @ManyToOne
and@OneToOne associations default to FetchType.EAGER! This default was standardized to allow Java Persistence provider implementations without lazy loading (in practice, such a persistence provider wouldn’t be very useful). We recommend that you default to the Hibernate lazy loading fetch plan by setting FetchType. LAZY in your to-one association mappings and only override it when necessary!

关于N+1次查询与使用抓取策略进行调优

首先明确一点:

lazy的集合是在第一次访问时通过一个select一次性加载出来的(不是在迭代时迭代一条select一条)。这就是N+1中的1。

在迭代过程中,如果要访问迭代元素依赖的其他对象或集合时,若它们是lazyload的,那么hibernate会生成一个select从数据库中加载出这个对象。N次循环就会生成n个select,这就是N+1中的N.

如上面所说,在映射时,我们应该遵从hibernate的默认抓取设置,即所有关联对象都是lazyload的。然后,我们应该在具体的事务中定制抓取策略,使得每次load的数据刚刚好,不多也不少,使得性能最优化。以下是Forum和Thread的一个典型例子:

1.未制定抓取计划。所有抓取按映射文档中的定义执行。(文档中定义的全部是lazy)

根据映射文档定义的抓取策略(所有关联对象,不管是单端还是集合都映射为fetch=lazy)生成的SQL.从SQL中可以看出:一开始只加载了Forum的基本信息,无任何关联对象。然后访问到Forum的Thread集合时,生成一条select,加载出全部的集合元素。然后再迭代集合的过程中生成一条一条的select查出每一个thread的subject post和author!
这也就是典型的N+1次查询问题。
Hibernate:
    /* Get Forum_1 */
 select
        this_.id as id2_0_,
        this_.creationTime as creation2_2_0_,
        this_.description as descript3_2_0_,
        this_.groupId as groupId2_0_,
        this_.modifiedTime as modified4_2_0_,
        this_.name as name2_0_
    from
        Forum this_
    where
        this_.id=?
Hibernate:
    /*  Get all threads of Forum_1.(Only thread's basic fields)*/
 select
        threads0_.forumId as forumId1_,
        threads0_.id as id1_,
        threads0_.id as id5_0_,
        threads0_.creationTime as creation2_5_0_,
        threads0_.forumId as forumId5_0_,
        threads0_.modifiedTime as modified3_5_0_,
        threads0_1_.subjectId as subjectId6_0_
    from
        Thread threads0_
    left outer join
        Thread_Subject threads0_1_
            on threads0_.id=threads0_1_.threadId
    where
        threads0_.forumId=?
/* Below is N+1 select! */
Hibernate:
    /* Select Thread_1's subject post */
 select
        post0_.id as id4_0_,
        post0_.authorId as authorId4_0_,
        post0_.creationTime as creation2_4_0_,
        post0_.isSubject as isSubject4_0_,
        post0_.messageBody as messageB4_4_0_,
        post0_.modifiedTime as modified5_4_0_,
        post0_.quotedPostId as quotedPo7_4_0_,
        post0_.threadId as threadId4_0_,
        post0_.title as title4_0_
    from
        Post post0_
    where
        post0_.id=?
Hibernate:
     /* Select Thread_1's subject post's author. */
 select
        user0_.id as id0_0_,
        user0_.accountNonExpired as accountN2_0_0_,
        user0_.accountNonLocked as accountN3_0_0_,
        user0_.credentialsNonExpired as credenti4_0_0_,
        user0_.email as email0_0_,
        user0_.enabled as enabled0_0_,
        user0_.password as password0_0_,
        user0_.username as username0_0_,
        user0_.version as version0_0_
    from
        User user0_
    where
        user0_.id=?
Hibernate:
     /* Select Thread_2's subject post */
  select
        post0_.id as id4_0_,
        post0_.authorId as authorId4_0_,
        post0_.creationTime as creation2_4_0_,
        post0_.isSubject as isSubject4_0_,
        post0_.messageBody as messageB4_4_0_,
        post0_.modifiedTime as modified5_4_0_,
        post0_.quotedPostId as quotedPo7_4_0_,
        post0_.threadId as threadId4_0_,
        post0_.title as title4_0_
    from
        Post post0_
    where
        post0_.id=?
Hibernate:
   /* Select Thread_2's subject post's author. */
 select
        user0_.id as id0_0_,
        user0_.accountNonExpired as accountN2_0_0_,
        user0_.accountNonLocked as accountN3_0_0_,
        user0_.credentialsNonExpired as credenti4_0_0_,
        user0_.email as email0_0_,
        user0_.enabled as enabled0_0_,
        user0_.password as password0_0_,
        user0_.username as username0_0_,
        user0_.version as version0_0_
    from
        User user0_
    where
        user0_.id=?

2.下面是通过join fetch重新制定了抓取计划后生成的sql。
Hibernate:
    /* Fetch all threads with subject post and author by left out join.*/
 select
        this_.id as id2_3_,
        this_.creationTime as creation2_2_3_,
        this_.description as descript3_2_3_,
        this_.groupId as groupId2_3_,
        this_.modifiedTime as modified4_2_3_,
        this_.name as name2_3_,
        threads2_.forumId as forumId5_,
        threads2_.id as id5_,
        threads2_.id as id5_0_,
        threads2_.creationTime as creation2_5_0_,
        threads2_.forumId as forumId5_0_,
        threads2_.modifiedTime as modified3_5_0_,
        threads2_1_.subjectId as subjectId6_0_,
        post3_.id as id4_1_,
        post3_.authorId as authorId4_1_,
        post3_.creationTime as creation2_4_1_,
        post3_.isSubject as isSubject4_1_,
        post3_.messageBody as messageB4_4_1_,
        post3_.modifiedTime as modified5_4_1_,
        post3_.quotedPostId as quotedPo7_4_1_,
        post3_.threadId as threadId4_1_,
        post3_.title as title4_1_,
        user4_.id as id0_2_,
        user4_.accountNonExpired as accountN2_0_2_,
        user4_.accountNonLocked as accountN3_0_2_,
        user4_.credentialsNonExpired as credenti4_0_2_,
        user4_.email as email0_2_,
        user4_.enabled as enabled0_2_,
        user4_.password as password0_2_,
        user4_.username as username0_2_,
        user4_.version as version0_2_
    from
        Forum this_
    left outer join
        Thread threads2_
            on this_.id=threads2_.forumId
    left outer join
        Thread_Subject threads2_1_
            on threads2_.id=threads2_1_.threadId
    left outer join
        Post post3_
            on threads2_1_.subjectId=post3_.id
    left outer join
        User user4_
            on post3_.authorId=user4_.id
    where
        this_.id=?

调优后的只生成一条sql,性能调优效果明显!

成lazy 

 

 

1

1

1

1

1

 

 

 

 

本文转载自:http://blog.csdn.net/bluishglc/article/details/5560574

共有 人打赏支持
猪刚烈
粉丝 22
博文 708
码字总数 110
作品 1
海淀
程序员
私信 提问
Hibernate中的抓取策略

抓取策略是指我们需要在关联对象间进行导航的时候,Hibernate如何获取关联对象的策略。 select抓取策略:当我们查询某个对象时,hibernate会另外发出一条select语句查询与之关联的实体或者集...

叶欢欢
2016/11/12
4
0
hibernate N+1问题

Hibernate N+1 问题及解决办法 问题出现的原因: Hibernate 中常会用到 set , bag 等集合表示 1 对多的关系,在获取实体的时候就能根据关系将关联的对象或者对象集取出,还可以设定 cacade...

毅屺
2016/03/20
77
0
MyBatis和Hibernate相比,优势在哪里?

1、开发对比开发速度 hibernate的真正掌握要比Mybatis来得难些。Mybatis框架相对简单很容易上手,但也相对简陋些。个人觉得要用好Mybatis还是首先要先理解好Hibernate。 开发社区 Hibernate ...

park
2017/11/28
0
0
MyBatis和Hibernate优劣势对比

1、开发对比 开发速度 Hibernate的真正掌握要比Mybatis来得难些。Mybatis框架相对简单很容易上手,但也相对简陋些。个人觉得要用好Mybatis还是首先要先理解好Hibernate。 开发社区 Hibernat...

黎嘉诚
2016/08/05
88
0
MyBatis和Hibernate相比,优势在哪里?

1、开发对比开发速度 Hibernate的真正掌握要比Mybatis来得难些。Mybatis框架相对简单很容易上手,但也相对简陋些。个人觉得要用好Mybatis还是首先要先理解好Hibernate。 开发社区 Hibernate ...

vshcxl
2016/03/28
41
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Cloud 分布式链路跟踪 Sleuth + Zipkin + Elasticsearch

随着业务越来越复杂,系统也随之进行各种拆分,特别是随着微服务架构的兴起,看似一个简单的应用,后台可能很多服务在支撑;一个请求可能需要多个服务的调用;当请求迟缓或不可用时,无法得知...

编程SHA
12分钟前
1
0
Swift-清除缓存

func removeCache (){ // 取出cache文件夹路径.如果清除其他位子的可以将cachesDirectory换成对应的文件夹 let cachePath = NSSearchPathForDirectoriesInDomains(FileMan...

west_zll
12分钟前
1
0
kl键盘事件

frameworks/base/data/keyboards路径下定义了很对kl文件。如Vendor_0416_Product_0300.kl,定义了某某遥控器的按键事件 # TVkey 103 DPAD_UPkey 108 DPAD_DOWNkey 105 DPAD_LEFTk...

安卓工程师王恒
15分钟前
1
0
CentOS 7 安装 Docker

工具: Oracle VM VirtualBox 虚拟机 ,本地电脑win10 系统: 虚拟机装 centos 7 前置条件: Docker 要求 CentOS 系统的内核版本高于 3.10 1. 通过 uname -r 命令查看当前的内核版本 2. 如果不够...

_大侠__
26分钟前
1
0
webrtc onAddStream回调流程

背景 webrtc代码基于M59 正文 1. 回调设置和处理 (1)java层先在监听器中实现回调处理函数,如下所示: private class PCObserver implements PeerConnection.Observer { @Override...

bill_shen
27分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部