文档章节

Hibernate的抓取策略

猪刚烈
 猪刚烈
发布于 2014/10/12 11:40
字数 1383
阅读 12
收藏 0
点赞 0
评论 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

 

 

 

 

© 著作权归作者所有

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

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

叶欢欢 ⋅ 2016/11/12 ⋅ 0

hibernate N+1问题

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

毅屺 ⋅ 2016/03/20 ⋅ 0

Hernate的优化方案

【IT168 技术文档】 一、批量修改和删除 在Hibernate 2中,如果需要对任何数据进行修改和删除操作,都需要先执行查询操作,在得到要修改或者删除的数据后,再对该数据进行相应的操作处理。在...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

Hibernate提升性能

导读:   20.1. 抓取策略(Fetching strategies)   抓取策略(fetching strategy)是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对...

wsl_Mr ⋅ 2013/07/24 ⋅ 1

MyBatis和Hibernate相比,优势在哪里?

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

qq5923dd411b8fa ⋅ 2017/05/23 ⋅ 0

MyBatis和Hibernate相比,优势在哪里?

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

park ⋅ 2017/11/28 ⋅ 0

MyBatis和Hibernate优劣势对比

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

黎嘉诚 ⋅ 2016/08/05 ⋅ 0

MyBatis和Hibernate相比,优势在哪里?

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

vshcxl ⋅ 2016/03/28 ⋅ 0

hibernate fetch属性

Hibernate的fetch="join"和fetch="select" 的一点分析 fetch参数指定了关联对象抓取的方式是select查询还是join查询,select方式时先查询返回要查询的主体对象(列表),再根据关联外键id,每...

zdatbit ⋅ 2016/07/18 ⋅ 0

cannot simultaneously fetch multiple bags 异常的解决办法

异常信息如下: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags ...... 问题是什么时候出现的呢? 当一个实体对象中包含多于一个non-lazy获取...

liangtee ⋅ 2012/10/09 ⋅ 1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

sbt网络问题解决方案

http://dblab.xmu.edu.cn/blog/maven-network-problem/

狐狸老侠 ⋅ 8分钟前 ⋅ 0

大数据,必须掌握的10项顶级安全技术

我们看到越来越多的数据泄漏事故、勒索软件和其他类型的网络攻击,这使得安全成为一个热门话题。 去年,企业IT面临的威胁仍然处于非常高的水平,每天都会看到媒体报道大量数据泄漏事故和攻击...

p柯西 ⋅ 52分钟前 ⋅ 0

Linux下安装配置Hadoop2.7.6

前提 安装jdk 下载 wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz 解压 配置 vim /etc/profile # 配置java环境变量 export JAVA_HOME=/opt/jdk1......

晨猫 ⋅ 57分钟前 ⋅ 0

crontab工具介绍

crontab crontab 是一个用于设置周期性被执行的任务工具。 周期性执行的任务列表称为Cron Table crontab(选项)(参数) -e:编辑该用户的计时器设置; -l:列出该用户的计时器设置; -r:删除该...

Linux学习笔记 ⋅ 今天 ⋅ 0

深入Java多线程——Java内存模型深入(2)

5. final域的内存语义 5.1 final域的重排序规则 1.对于final域,编译器和处理器要遵守两个重排序规则: (1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用...

江左煤郎 ⋅ 今天 ⋅ 0

面试-正向代理和反向代理

面试-正向代理和反向代理 Nginx 是一个高性能的反向代理服务器,但同时也支持正向代理方式的配置。

秋日芒草 ⋅ 今天 ⋅ 0

Spring 依赖注入(DI)

1、Setter方法注入: 通过设置方法注入依赖。这种方法既简单又常用。 类中定义set()方法: public class HelloWorldOutput{ HelloWorld helloWorld; public void setHelloWorld...

霍淇滨 ⋅ 昨天 ⋅ 0

马氏距离与欧氏距离

马氏距离 马氏距离也可以定义为两个服从同一分布并且其协方差矩阵为Σ的随机变量之间的差异程度。 如果协方差矩阵为单位矩阵,那么马氏距离就简化为欧氏距离,如果协方差矩阵为对角阵,则其也...

漫步当下 ⋅ 昨天 ⋅ 0

聊聊spring cloud的RequestRateLimiterGatewayFilter

序 本文主要研究一下spring cloud的RequestRateLimiterGatewayFilter GatewayAutoConfiguration @Configuration@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMi......

go4it ⋅ 昨天 ⋅ 0

Spring clound 组件

Spring Cloud技术应用从场景上可以分为两大类:润物无声类和独挑大梁类。 润物无声,融合在每个微服务中、依赖其它组件并为其提供服务。 Ribbon,客户端负载均衡,特性有区域亲和、重试机制。...

英雄有梦没死就别停 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部