Hibernate——缓存
文章目录
- 一、对象状态
- 1.1 临时/瞬时状态
- 1.2 持久化状态
- 1.3 游离状态
- 二、一级缓存
- 2.1 含义
- 2.2 缓存相关的方法
- 2.2.1 clear
- 2.2.2 flush
- 2.2.3 方法适用场景
- 2.3 Iterator与list
- 2.4 懒加载
- 2.4.1 修改懒加载
- 2.4.2 懒加载异常
- 三、二级缓存
- 3.1 含义
- 3.2 配置二级缓存
- 3.2.1 开启二级缓存
- 3.2.2 指定缓存框架
- 3.2.3 指定哪些类加入二级缓存
- 3.2.4 测试
- 3.3 二级缓存策略
- 3.4 集合缓存
- 3.4.1 集合配置二级缓存
- 3.4.2 测试
- 3.5 查询缓存
一、对象状态
参考:https://mp.weixin.qq.com/s/VFnny3ou48w9bIgTT0xVow
1.1 临时/瞬时状态
含义:直接new出来的对象就是临时/瞬时状态的。
特点:
——该对象还没有被持久化【没有保存在数据库中】
——不受Session的管理
User user = new User();
IdCard idCard = new IdCard();
// 这样,对象处于临时/瞬时状态了
1.2 持久化状态
含义:当保存在数据库中的对象就是持久化状态。
当调用session的save/saveOrUpdate/get/load/list等方法时,对象就是持久化状态
特点:
——在数据库有对应的数据
——受Session的管理
——当对对象属性进行更改的时候,会反映到数据库中!
session.save(idCard);
transaction.commit();
// 这样,对象处于持久化状态了。
1.3 游离状态
含义:当Session关闭了以后,持久化的对象就变成了游离状态了。
特点:
——在数据库有对应的数据
——不处于session的管理
session.save(idCard);
transaction.commit();
session.close();
// 这样,对象处于游离状态了。
二、一级缓存
2.1 含义
项目 | 含义 |
---|---|
Hibenate中一级缓存 | 也叫做session的缓存。 |
目的 | 在session范围内,减少对数据库的访问次数!从而提升hibernate的执行效率! |
有效范围 | session。 Session关闭,一级缓存失效! |
注意:
1、持久化状态的对象,都受Session管理,都会在Session缓存中!
2、Session的缓存由hibernate维护,用户不能操作缓存内容。
3、 若想操作缓存内容,必须通过hibernate提供的evit/clear方法操作。
示例说明:
1、更新数据库
已知:user表中(id = 1,username=“张珊”)。
目的:把id=1的username改为“张珊”。
// 获取id=1的对象信息。
User user = (User)session.get(User.class,1);
// 修改username为“张珊”。
user.setUsername("张珊");
// 提交事务。
transaction.commit();
// 关闭session。
session.close();
结果:只有一条查询SQL,并没有更新SQL。
原因:查询的结果被缓存了。修改后的数据与缓存的数据一样,所以没有执行更新操作。
2、获取数据
已知:user表中(id = 1,username=“张珊”)。
目的:二次获取该信息。
User user = null;
user = (User)session.get(User.class,1); // 一次获取
user = (User)session.get(User.class,1);// 二次获取
// 提交事务。
transaction.commit();
// 关闭session。
session.close();
结果:只有一条查询SQL。
原因:一次查询的结果被缓存了。 二次获取直接从缓存中获取。
2.2 缓存相关的方法
常用的方法 | 作用 |
---|---|
session.flush(); | 让一级缓存与数据库同步 |
session.evict(arg0); | 清空一级缓存中指定的对象 |
session.clear(); | 清空一级缓存中缓存的所有对象 |
2.2.1 clear
User user = null;
user = (User) session.get(User.class, 1);
//清除缓存,那么下面获取的时候,就不能从缓存里面拿了
session.clear();
user = (User) session.get(User.class, 1);
// 结果:执行两次查询语句。
2.2.2 flush
在有缓存的情况下,修改同一条记录的数据,以最后的为准…因此只有一条update
User user = null;
user = (User) session.get(User.class, 1);
user.setUsername("李四");
user = (User) session.get(User.class, 1);
user.setUsername("王五");
// 结果:执行一次更新SQL语句。
强制让它和数据库同步的话,就有两条update了
User user = null;
user = (User) session.get(User.class, 1);
user.setUsername("李四");
session.flush();
user = (User) session.get(User.class, 1);
user.setUsername("王五");
// 结果:执行两次更新SQL语句。
2.2.3 方法适用场景
一般地,我们在批处理的时候会用,因为缓存也是有大小的。
思路:
——每隔一定记录数,先与数据库同步 flush()
——再清空缓存 clear()
注意:不同的Session是不会共享缓存的!
2.3 Iterator与list
使用HQL查询全部数据的时候,可以使用list()得到所有的数据,也可以使用iterator()得到一个迭代器,再遍历迭代器。
二者都可以获取缓存的数据。
2.4 懒加载
含义:当使用数据的时候才去获取数据、执行对应的SQL语句…当还没用到数据的时候,就不加载对应的数据!
作用:提高Hibernate的性能,提高执行效率!
——get: 及时加载,只要调用get方法立刻向数据库查询
——load:默认使用懒加载,当用到数据的时候才向数据库查询。
user = (User) session.get(User.class, 1);
user = (User) session.load(User.class, 1);
2.4.1 修改懒加载
<class name="IdCard" table="IdCard" lazy="false">
属性值:
true 使用懒加载
false 关闭懒加载
extra (在集合数据懒加载时候提升效率)【只有在set、list等集合标签中使用】
——在真正使用数据的时候才向数据库发送查询的sql;
——如果调用集合的size()/isEmpty()方法,只是统计,不真正查询数据!
2.4.2 懒加载异常
当Session关闭后,就不能使用懒加载了,否则会报出异常。
session.close();
System.out.println(user);
// 结果:报出异常。
异常解决方法 | 含义 | 示例 |
---|---|---|
方式1 | 先使用一下数据 | dept.getDeptName(); |
方式2 | 强迫代理对象初始化 | Hibernate.initialize(dept); |
方式3 | 关闭懒加载 | 设置lazy=false; |
方式4 | 在使用数据之后,再关闭session! |
三、二级缓存
3.1 含义
项目 | 含义 |
---|---|
来源 | Hibernate自带 |
含义 | 基于应用程序的缓存 |
范围 | 所有的Session都可以使用 |
存储内容 | 存储的是常用的类 |
注意:Hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架!
——若想用二级缓存,只需在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影响代码。
——若觉得hibernate提供的框架框架不好用,自己可以换其他的缓存框架或自己实现缓存框架都可以。
3.2 配置二级缓存
二级缓存是Hibernate自带的,可以在hibernate.properties文件中找到对应的信息。
hibernate.properties:
#hibernate.cache.use_second_level_cache false【二级缓存默认不开启,需要手动开启】
#hibernate.cache.use_query_cache true 【开启查询缓存】
## choose a cache implementation 【二级缓存框架的实现】
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider
hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider 默认实现
#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider
#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
配置步骤:
1)开启二级缓存
2)指定缓存框架
3)指定哪些类加入二级缓存
3.2.1 开启二级缓存
在hibernate.cfg.xml文件中开启二级缓存
<!-- a. 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
3.2.2 指定缓存框架
指定Hibernate自带的二级缓存框架就好了
<!-- b. 指定使用哪一个缓存框架(默认提供的) -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
3.2.3 指定哪些类加入二级缓存
<!-- c. 指定哪一些类,需要加入二级缓存 -->
<class-cache usage="read-write" class="com.my.entity.Monkey"/>
<class-cache usage="read-only" class="com.my.entity.Cat"/>
3.2.4 测试
一级缓存是Session的缓存,那么我们在测试二级缓存的时候使用两个Session来测试就好了。如果第二个Session拿到的是缓存数据,那么就证明二级缓存是有用的。
public static void testCache2() {Session session1 = getSession();Transaction transaction = session1.getTransaction();transaction.begin();Monkey monkey = (Monkey) session1.get(Monkey.class,"40283f815be67f42015be67f43240001" );System.out.println(monkey.getName());Session session2 = factory.openSession();Transaction transaction2 = session2.getTransaction();transaction2.begin();Monkey monkey2 = (Monkey) session1.get(Monkey.class, "40283f815be67f42015be67f43240001");System.out.println(monkey2.getName());//提交事务transaction.commit();transaction2.commit();//关闭Sessionsession1.close();session2.close();
}
结果:只有一个查询语句。输出正确结果。说明二级缓存生效。
3.3 二级缓存策略
<!-- c. 指定哪一些类,需要加入二级缓存 -->
<class-cache usage="read-write" class="com.my.entity.Monkey"/>
<class-cache usage="read-only" class="com.my.entity.Cat"/>
属性值 | 含义 |
---|---|
read-only | 放入二级缓存的对象,只读; |
read-write | 放入二级缓存的对象,可以读、写; |
非严格的读写
(基于事务的策略)
3.4 集合缓存
问题:在数据库查询的数据是集合时,Hibernate默认是没有为集合数据设置二级缓存的。因此,还需要去读写数据库的信息。
3.4.1 集合配置二级缓存
在hibernate.cgf.xml中配置对象中的集合为二级缓存。
<!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] -->
<collection-cache usage="read-write" collection="cn.itcast.b_second_cache.Dept.emps"/>
3.4.2 测试
public static void testCache() {Session session1 = sf.openSession();session1.beginTransaction();// a. 查询一次Dept dept = (Dept) session1.get(Dept.class, 10);dept.getEmps().size();// 集合session1.getTransaction().commit();session1.close();System.out.println("------");// 第二个sessionSession session2 = sf.openSession();session2.beginTransaction();// a. 查询一次dept = (Dept) session2.get(Dept.class, 10); // 二级缓存配置好; 这里不查询数据库 dept.getEmps().size();session2.getTransaction().commit();session2.close();
}
3.5 查询缓存
问题:list()和iterator()会把数据放在一级缓存,但一级缓存只在Session的作用域中有效。如果想要跨Session来使用,就要设置查询缓存
1、默认的查询数据是不放在二级缓存中的。
2、若想把查询数据放到二级缓存,就需要在配置文件中开启。
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
在使用程序查询的时候,也要调用setCacheable()方法,设置为查询缓存。
public static void listCache() {Session session1 = sf.openSession();session1.beginTransaction();// HQL查询 【setCacheable 指定从二级缓存找,或者是放入二级缓存】Query q = session1.createQuery("from Dept").setCacheable(true);System.out.println(q.list());session1.getTransaction().commit();session1.close();Session session2 = sf.openSession();session2.beginTransaction();q = session2.createQuery("from Dept").setCacheable(true);System.out.println(q.list()); // 不查询数据库: 需要开启查询缓存session2.getTransaction().commit();session2.close();}
Hibernate——缓存相关推荐
- Hibernate缓存原理与策略 Hibernate缓存原理:
Hibernate缓存原理: 对于Hibernate这类ORM而言,缓存显的尤为重要,它是持久层性能提升的关键.简单来讲Hibernate就是对JDBC进行封装,以实现内部状态的管理,OR关系的映射等 ...
- Hibernate 缓存机制
转载:http://www.cnblogs.com/wean/archive/2012/05/16/2502724.html 一.why(为什么要用Hibernate缓存?) Hibernate是一个 ...
- Hibernate 缓存
我这里使用的是Hibernate5.2.0版本 Hibernate缓存分为一级缓存(有的也叫Session缓存)和二级缓存. 一级缓存(Session) 一级缓存的生命周期和session的生命周期一 ...
- 【大话Hibernate】hibernate缓存详解
为什么要用hibernate缓存? hibernate是一个持久层框架,经常访问物理数据库.为了降低应用程序对物理数据源访问的次数,从而提高应用程序的运行性能,我们想到使用hibernate缓存机制. ...
- (11) Hibernate 缓存机制
一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数 ...
- 初识Hibernate 缓存
生活就像一杯咖啡,让你我慢慢的品尝,品尝它的苦涩和甘甜...... 一.什么是Hibernate缓存. 解析:白话来说就是缓存数据的容器 官方标准点缓存:是计算机领域的概念,它介于应用程序和永久性数据 ...
- hazelcast 使用_使用HazelCast进行Hibernate缓存:JPA缓存基础知识
hazelcast 使用 HazelCast的最大功能之一就是对Hibernate第二级缓存的支持 . JPA具有两个级别的缓存. 一级缓存在事务期间缓存对象的状态. 通过两次查询相同的对象,您必须获 ...
- Hibernate缓存级别教程
开始使用Hibernate的人们常见的问题之一就是性能,如果您没有太多的Hibernate经验,您会发现应用程序变慢的速度. 如果启用sql跟踪,您将看到有多少查询被发送到数据库,而这些查询几乎不需要 ...
- hibernate缓存机制与N+1问题
在项目中遇到的趣事 本文基于hibernate缓存机制与N+1问题展开思考, 先介绍何为N+1问题 再hibernate中用list()获得对象: 1 /** 2 * 此时会发出一条sql,将30个学 ...
- Hibernate缓存 - 第一级缓存
Hibernate缓存 - 第一级缓存 欢迎使用Hibernate缓存 - 一级缓存示例教程.最近我们研究了Hibernate架构,hibernate映射以及如何使用HQL以面向对象的方式触发SQL查 ...
最新文章
- ASP.NET Core 源码学习之 Options[4]:IOptionsMonitor
- python语言中包含的标准数据类型_python标准数据类型(笔记一)
- 解决 An invalid domain was specified for this cookie
- Linux API函数总结
- python seo百度_Python与seo,百度关键词相关搜索关键词采集源码
- Isolate -- Be Forget Feature Of The Object-Orient Programming
- 数字图像处理-空间域图像增强
- 镜头相关的基本参数总结
- 安装好office套件以后,右键新建中没有Word、Excel、PPT等怎么办
- 给陈景润之子陈由伟的一封公开信
- 用计算机画画教学设计,电脑版你画画教学设计
- Unable to start service Intent U=0: not found
- I. chino with mates
- Python扩展包:Unofficial Windows Binaries for Python Extension Packages
- Location iOS12.3驱动分享
- 中班音乐会跳舞的机器人_中班音乐《会跳舞的身体》
- 被人打了要不要还手呢?
- MediaPlayer,切歌进入setOnCompletionListener的问题
- 基于51单片机NRF24L01的远程水压监控及控制proteus仿真原理图PCB
- Java实验报告一(完全数、一年四季、杨辉三角、path和classpath区别、next()和nextLine()区别)
热门文章
- TBtools:基因家族分析简单流程
- 计算机显示屏显示超出屏幕大小,电脑连接的显示器出错显示超出工作频率范围怎么恢复...
- vue网页调用高德获取经纬度
- centos:清理磁盘空间
- 图像相似度的评价指标 : FID(Fréchet Inception Distance)
- CC2430 定时器溢出中断 详解
- ant-desigh+prolayout布局,修改面包屑的分隔符号,百度搜遍了都找不到办法,csdn解决了
- 企业财务报表分析【1】
- win10计算机域填写,win10系统如何加入域 win10系统加入域的方法
- 设计模式(三) 抽象工厂模式