文档章节

hibernate缓存详解

翰霖学院
 翰霖学院
发布于 2017/07/24 08:59
字数 1642
阅读 4
收藏 1

这里写图片描述
这里写图片描述

N+1问题

所谓N+1问题,使用hibernate查询数据,首先返回数据的id信息,并没有返回所有的对象信息,只有在真正使用的时候,在使用这个id对数据库中查询数据,一次查询多次调用数据库(缓存)的情况,就是所谓的N+1问题。以下方法或者策略会出现N+1问题:

1.使用iterate()方法

存在iterator的原因是,有可能会在一个session中查询两次数据,如果使用list每一次都会把所有的对象查询上来
,如果使用iterator仅仅只会查询id,此时所有的对象已经存储在一级缓存(session的缓存)中,可以直接获取

    /** 
       * Return the query results as an <tt>Iterator</tt>. If the query 
       * contains multiple results per row, the results are returned in 
       * an instance of <tt>Object[]</tt>.<br> * <br> 
       * Entities returned as results are initialized on demand. The first 
       * SQL query returns identifiers only.<br> * 
       * @return the result iterator 
      */
    Iterator<R> iterate();

2.使用查询缓存策略

一级缓存,session级别缓存

首次查询数据,会查询数据库返回数据,并且保存到缓存中;再次查询该数据时,直接从缓存中获取(同一个session)。
由于一级缓存是session级别的缓存,只有在同一个session中才能起到再次查询从缓存中获取数据。
比如:list()放入缓存,load查询从缓存中获取数据。

由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。
Session级缓存是必需的,不允许而且事实上也无法卸除。在Session级缓存中,持久化类的每个实例都具有唯一的ID
调用session的方法会加入一级缓存:save()、update()、savaeOrUpdate()、get()或load();调用查询接口的list()、iterate()或filter()方法

二级缓存(sessionFactory级别)

相关配置

下载ehcache相关包

在hibernate.cfg.xml配置文件中配置我们二级缓存的一些属性

<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 二级缓存的提供类 在hibernate4.0版本以后我们都是配置这个属性来指定二级缓存的提供类-->
<property name="hibernate.cache.region.factory_class">
    org.hibernate.cache.ehcache.EhCacheRegionFactory<
/property>
<!-- 4.0之前版本的配置 
<property name="hibernate.cache.provider_class">
    net.sf.ehcache.hibernate.EhCacheProvider
</property>-->
<!-- 二级缓存配置文件的位置 -->
property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property>

配置ehcache.xml

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created. 
         If the path is a Java System Property it is replaced by its value in the running VM. 
         The following properties are translated: 
         user.home - User's home directory 
         user.dir - User's current working directory 
         java.io.tmpdir - Default temp file path -->

  <!--指定二级缓存存放在磁盘上的位置-->
    <diskStore path="user.dir"/>  

  <!--我们可以给每个实体类指定一个对应的缓存,如果没有匹配到该类,则使用这个默认的缓存配置-->
    <defaultCache  maxElementsInMemory="10000"  //在内存中存放的最大对象数 
                   eternal="false"         //是否永久保存缓存,设置成false                
                   timeToIdleSeconds="120"     
                   timeToLiveSeconds="120"     
                   overflowToDisk="true"     //如果对象数量超过内存中最大的数,是否将其保存到磁盘中,设置成true />

  <!--     
    1、timeToLiveSeconds的定义是:以创建时间为基准开始计算的超时时长;     
    2、timeToIdleSeconds的定义是:在创建时间和最近访问时间中取出离现在最近的时间作为基准计算的超时时长;  
    3、如果仅设置了timeToLiveSeconds,则该对象的超时时间=创建时间+timeToLiveSeconds,假设为A;     
    4、如果没设置timeToLiveSeconds,则该对象的超时时间=max(创建时间,最近访问时间)+timeToIdleSeconds,假设为B;     
    5、如果两者都设置了,则取出A、B最少的值,即min(A,B),表示只要有一个超时成立即算超时。   -->

  <!--可以给每个实体类指定一个配置文件,通过name属性指定,要使用类的全名-->
    <cache 
          name="com.sunld.bean.User" 
          maxElementsInMemory="10000" 
          eternal="false" 
          timeToIdleSeconds="300" 
          timeToLiveSeconds="600" 
          overflowToDisk="true" 
    />

    <cache name="sampleCache2" 
           maxElementsInMemory="1000" 
           eternal="true" 
           timeToIdleSeconds="0" 
           timeToLiveSeconds="0" 
           overflowToDisk="false" 
    /> -->


</ehcache>

开启缓存

①如果使用xml配置,我们需要在 *.hbm.xml 中加上一下配置

②如果使用annotation配置,我们需要在类上加上这样一个注解
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)

缓存策略

read-only、nonstrict-read-write、read-write、transactional

二级缓存触发的方法

save、update、saveOrupdate、load、get、list、query、Criteria方法都会填充二级缓存
get、load、iterate会从二级缓存中取数据

session.save(user)
如果user主键使用“native”生成,则不放入二级缓存

执行顺序

1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。
2) 把获得的所有数据对象根据ID放入到第二级缓存中。
3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;
查不到,再查询数据库,把结果按照ID放入到缓存。
4) 删除、更新、增加数据的时候,同时更新缓存。

其他

二级缓存缓存的仅仅是对象,如果查询出来的是对象的一些属性,则不会被加到缓存中去
Hibernate的二级缓存策略,是针对于ID查询的缓存策略,对于条件查询则毫无作用。为此,Hibernate提供了针对条件查询的查询缓存(Query Cache)。

解决N+1问题

当我们如果需要查询出两次对象的时候,可以使用二级缓存来解决N+1的问题
先list在iterator

查询缓存(sessionFactory级别)

开启缓存

hibernate.cfg.xml

<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>

查询中需要调用方法

.setCacheable(true) //开启查询缓存,查询缓存也是SessionFactory级别的缓存 
如果使用注解方式,需要在类上加入在类上加注解:@Cacheable

其他

只有当 HQL 查询语句完全相同时,连参数设置都要相同,此时查询缓存才有效
查询缓存也能引起 N+1 的问题,需要开启二级缓存。
查询普通属性,会先到查询缓存中取,如果没有,则查询数据库;
查询实体,会先到查询缓存中取id,如果有,则根据id到缓存(一级/二级)中取实体,如果缓存中取不到实体,再查询数据库。

缓存策略提供商

org.hibernate.cache.HashtableCacheProvider(内存)
org.hibernate.cache.EhCacheProvider(内存,硬盘)
org.hibernate.cache.OSCacheProvider(内存,硬盘)
org.hibernate.cache.SwarmCacheProvider(能用于集群环境)
org.hibernate.cache.TreeCacheProvider(能用于集群环境)
org.hibernate.cache.jbc.JBossCacheRegionFactory(能用于集群环境)

© 著作权归作者所有

翰霖学院
粉丝 0
博文 67
码字总数 45112
作品 0
济南
高级程序员
私信 提问
史上最简单的Hibernate4视频教程(附源码和笔记)

Hibernate4是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合...

2846613430
2016/04/08
1K
0
Hibernate缓存策略详解

Hibernate缓存策略 1. 数据缓存 1.1. 概述 缓存是数据库数据临时容器,它包含了库表数据的临时拷贝,位于数据库与数据访问层之间。 ORM 在进行数据读取时,会根据其缓存管理策略,首先在内存...

提广乾
2012/09/11
181
0
Hibernate properties详解

Hibernate properties Hibernate配置属性 属性名 用途 hibernate.dialect ;一个Hibernate Dialect类名允许Hibernate针对特定的关系数据库生成优化的SQL. 取值 full.classname.of.Dialect hi...

7788
2014/04/02
123
0
hibernate xml配置文件参数详解

Hibernate 参数设置一览表 表 3.4. Hibernate JDBC和连接(connection)属性 表 3.5. Hibernate缓存属性 表 3.6. Hibernate事务属性 表 3.7. 其他属性 你应当总是为你的数据库将hibernate.dia...

laigous
2013/01/17
217
0
hibernate缓存机制详解

hibernate的一级缓存 hibernate是一个线程对应一个session,一个线程可以看成一个用户。也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了。 hi...

偶尔诗文
2015/05/09
159
0

没有更多内容

加载失败,请刷新页面

加载更多

如何编写高质量的 JS 函数(1) -- 敲山震虎篇

本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/7lCK9cHmunvYlbm7Xi7JxQ 作者:杨昆 一千个读者,有一千个哈姆雷特。 此系列文章将会从函数的执行机制、鲁棒性、函...

vivo互联网技术
38分钟前
5
0
学会这5个Excel技巧,让你拒绝加班

在网上,随处都可以看到Excel技巧,估计已看腻了吧?但下面5个Excel技巧会让你相见恨晚。关键的是它们个个还很实用 图一 技巧1:快速删除边框 有时当我们处理数据需要去掉边框,按Ctrl+Shif...

干货趣分享
今天
11
0
JS基础-该如何理解原型、原型链?

JS的原型、原型链一直是比较难理解的内容,不少初学者甚至有一定经验的老鸟都不一定能完全说清楚,更多的"很可能"是一知半解,而这部分内容又是JS的核心内容,想要技术进阶的话肯定不能对这个...

OBKoro1
今天
9
0
高防CDN的出现是为了解决网站的哪些问题?

高防CDN是为了更好的服务网络而出现的,是通过高防DNS来实现的。高防CDN是通过智能化的系统判断来路,再反馈给用户,可以减轻用户使用过程的复杂程度。通过智能DNS解析,能让网站访问者连接到...

云漫网络Ruan
今天
15
0
OSChina 周一乱弹 —— 熟悉的味道,难道这就是恋爱的感觉

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @xiaoshiyue :好久没分享歌了分享张碧晨的单曲《今后我与自己流浪》 《今后我与自己流浪》- 张碧晨 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
3.3K
25

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部