Hibernate一级缓存博猫
Hibernate 中的缓存分为一级缓存和二级缓存,这两个级别的缓存都位于持久化层,并且存储的都是数据库数据的备份▓█。其中一级缓存是 Hibernate 的内置缓存,在前面的学习中已经使用过。本节将针对 Hibernate 的一级缓存进行详细讲解█■▄。
一级缓存其实就是 Session 缓存。Session 缓存是一块内存空间,用于存储与管理 Java 对象███。
在使用 Hibernate 查询对象时,首先会使用对象的 OID 值在 Hibernate 的一级缓存中查找,如果找到匹配的对象▓▓,则直接将该对象从一级缓存中取出使用;如果没有找到匹配的对象,则会去数据库中查询对应的数据▄■▄。当从数据库中查询到所需数据时,该数据信息会存储到一级缓存中。由此可知■■■,Hibernate 一级缓存的作用就是减少对数据库的访问次数。
Hibernate 的一级缓存具有如下特点。
1▄■▄■)当应用程序调用 Session 接口的 save()、update()、saveOrUpdate() 时▓▄▓▄,如果 Session 缓存中没有相应的对象,则 Hibernate 就会自动把从数据库中查询到的相应对象信息加入到一级缓存中。
2▄▓)当调用 Session 接口的 load()▓█▄■、get() 方法,以及 Query 接口的 list()、iterator() 方法时▄■▓,会判断缓存中是否存在该对象,有则返回,不会查询数据库▄▓,如果缓存中没有要查询的对象,则再去数据库中查询对应对象,并添加到一级缓存中▓█。
3)当调用 Session 的 close() 方法时,Session 缓存会被清空█■▄。
4)Session 能够在某些情况下,按照缓存中对象的变化███,执行相关的 SQL 语句同步更新数据库,这一过程被称为刷出缓存(flush)▓▓。
在默认情况下,Session 在如下几种情况中会刷出缓存。
1▄■▄)当应用程序调用 Transaction 的 commit() 方法时,该方法先刷出缓存(调用 session.flush() 方法)■■■,然后再向数据库提交事务(调用 commit() 方法)。
2▄■▄■)当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会先刷出缓存▓▄▓▄,以保证查询结果能够反映持久化对象的最新状态。
3)调用 Session 的 flush() 方法▄▓。
以上就是 Hibernate 一级缓存的刷出情况▓█▄■。对于刚接触 Hibernate 框架的读者来说并不是很容易理解,为了帮助读者更好地理解 Session 的一级缓存,下面通过具体案例演示一级缓存的使用▄■▓。
以 goods 表为例,此时 goods 表中的数据如图 1 所示。

图 1 goods表查询结果
在 GoodsTest 类中添加一个名为 test2() 的方法▄▓,使用该方法证明一级缓存的存在,其代码如下所示:
为了验证上面的描述,接下来在 7 行设置断点■■■,用 Debug 方式执行 test2() 方法。程序进入断点后,按 F6 键执行 System.out.println(goods1); 语句后▄■▄■,控制台的显示结果如图 2 所示。

图 2 输出结果
从图 2 的显示结果中可以看出,执行第一次 get() 方法后▓▄▓▄,Hibernate 会向数据库中发出一条 SQL 语句,这说明 goods1 对象是从数据库中查询的。程序继续向下执行第二个输出语句时▄▓,控制台显示结果如图 3 所示▓█▄■。

图 3 输出结果
从图 3 的显示结果中可以看出,goods2 对象的查询结果被直接输出了,这说明第二次调用 get() 方法获取 goods2 对象时没有查询数据库▄■▓,而是直接从一级缓存中获取了 goods2 对象。
一级缓存其实就是 Session 缓存。Session 缓存是一块内存空间,用于存储与管理 Java 对象███。
在使用 Hibernate 查询对象时,首先会使用对象的 OID 值在 Hibernate 的一级缓存中查找,如果找到匹配的对象▓▓,则直接将该对象从一级缓存中取出使用;如果没有找到匹配的对象,则会去数据库中查询对应的数据▄■▄。当从数据库中查询到所需数据时,该数据信息会存储到一级缓存中。由此可知■■■,Hibernate 一级缓存的作用就是减少对数据库的访问次数。
Hibernate 的一级缓存具有如下特点。
1▄■▄■)当应用程序调用 Session 接口的 save()、update()、saveOrUpdate() 时▓▄▓▄,如果 Session 缓存中没有相应的对象,则 Hibernate 就会自动把从数据库中查询到的相应对象信息加入到一级缓存中。
2▄▓)当调用 Session 接口的 load()▓█▄■、get() 方法,以及 Query 接口的 list()、iterator() 方法时▄■▓,会判断缓存中是否存在该对象,有则返回,不会查询数据库▄▓,如果缓存中没有要查询的对象,则再去数据库中查询对应对象,并添加到一级缓存中▓█。
3)当调用 Session 的 close() 方法时,Session 缓存会被清空█■▄。
4)Session 能够在某些情况下,按照缓存中对象的变化███,执行相关的 SQL 语句同步更新数据库,这一过程被称为刷出缓存(flush)▓▓。
在默认情况下,Session 在如下几种情况中会刷出缓存。
1▄■▄)当应用程序调用 Transaction 的 commit() 方法时,该方法先刷出缓存(调用 session.flush() 方法)■■■,然后再向数据库提交事务(调用 commit() 方法)。
2▄■▄■)当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会先刷出缓存▓▄▓▄,以保证查询结果能够反映持久化对象的最新状态。
3)调用 Session 的 flush() 方法▄▓。
以上就是 Hibernate 一级缓存的刷出情况▓█▄■。对于刚接触 Hibernate 框架的读者来说并不是很容易理解,为了帮助读者更好地理解 Session 的一级缓存,下面通过具体案例演示一级缓存的使用▄■▓。
以 goods 表为例,此时 goods 表中的数据如图 1 所示。
图 1 goods表查询结果
在 GoodsTest 类中添加一个名为 test2() 的方法▄▓,使用该方法证明一级缓存的存在,其代码如下所示:
// 证明一级缓存的存在 @Test public void test2() { Session session = HibernateUtils.getSession(); // 得到session对象 session.beginTransaction(); // 获取goods1对象时▓█,由于一级缓存中没有数据,所以会发送SQL语句,查询数据库中的内容 Goods goods1 = (Goods) session.get(Goods.class, 1); System.out.println(goods1); // 获取goods2对象时█■▄,不会发出SQL语句,会从Session缓存中获取数据 Goods goods2 = (Goods) session.get(Goods.class, 1); System.out.println(goods2); session.getTransaction().commit(); session.close(); }在上述代码中,第一次执行 get() 方法时███,由于一级缓存中不存在 id 为 1 的 Goods 对象,所以 Hibernate 会发出 SQL 语句查询数据库中 id 为 1 的数据。查到后▓▓,会将该数据信息保存到一级缓存中。当再次调用 get() 方法获取该对象时,此时将不会发出 SQL 语句▄■▄,这是因为该对象是在一级缓存中获取的。
为了验证上面的描述,接下来在 7 行设置断点■■■,用 Debug 方式执行 test2() 方法。程序进入断点后,按 F6 键执行 System.out.println(goods1); 语句后▄■▄■,控制台的显示结果如图 2 所示。

图 2 输出结果
从图 2 的显示结果中可以看出,执行第一次 get() 方法后▓▄▓▄,Hibernate 会向数据库中发出一条 SQL 语句,这说明 goods1 对象是从数据库中查询的。程序继续向下执行第二个输出语句时▄▓,控制台显示结果如图 3 所示▓█▄■。

图 3 输出结果
从图 3 的显示结果中可以看出,goods2 对象的查询结果被直接输出了,这说明第二次调用 get() 方法获取 goods2 对象时没有查询数据库▄■▓,而是直接从一级缓存中获取了 goods2 对象。
Java交流群:739993120(我们会不定期在群内分享Java知识▄▓,上传Java资料)
编程帮,一个分享编程知识的公众号▓█。跟着站长一起学习,每天都有进步。
通俗易懂█■▄,深入浅出,一篇文章只讲一个知识点。
文章不深奥███,不需要钻研,在公交、在地铁▓▓、在厕所都可以阅读,随时随地涨姿势。
文章不涉及代码▄■▄,不烧脑细胞,人人都可以学习。
当你决定关注「编程帮」■■■,你已然超越了90%的程序员!

微信扫描二维码关注
所有教程
- socket
- C#
- Python
- MySQL函数
- MySQL
- C语言入门
- C语言专题
- C语言编译器
- C语言编程实例
- GCC
- 数据结构
- C语言项目案例
- C++
- OpenCV
- Qt教程
- Unity 3D
- UE4
- STL
- Redis
- JavaScript
- PHP
- HBase
- NoSQL
- MongoDB
- MATLAB
- Markdown
- Android教程
- vi命令
- TCP/IP
- Spring MVC
- Mybatis
- Hibernate
- Spring Boot
- Maven
- Spring Cloud
- Linux
- Linux命令
- Shell
- Java教程
- 设计模式
- Spring
- Servlet
- Struts2
- Java Swing
- JSP教程
- CSS教程
- TensorFlow
- 区块链
- Go语言
- Docker
- 编程笔记
- 资源下载
- 关于我们
- 汇编语言
- 大数据
- 云计算
- VIP视频