hibernate缓存学习之【一级缓存】

2024-08-25 14:48
文章标签 学习 缓存 hibernate 一级

本文主要是介绍hibernate缓存学习之【一级缓存】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        最先接触到缓存机制是在学习计算机操作系统原理时,计算机的缓存机制是为了解决CPU和内存的速度差异。CPU存取数据的速度非常快,相对CPU来说内存的速度就慢很多。CPU需要从内存中读取一些数据但是由于内存的速度慢就无法及时提供,所以内存中使用最频繁的数据、指令会被复制到CPU的缓存中CPU就不需要总是和内存打交道这样可以提高效率。CPU的缓存也分为一级和二级,在实际访问中会先找一级缓存,一级没有就会找二级缓存如果二级缓存中也没有就只能到内存中查找。详细原理小编还需要进一步了解。

对比操作系统的缓存机制我们会发现hibernate的缓存机制大体上和操作系统是一致的。

Why:

       为什么hibernate会出现缓存机制?因为hibernate是属于持久层的所以会频繁的和数据库打交道进行数据的读取,正如CPU需要从内存中读取数据类似。为了减少程序运行时访问物理数据源的次数提高运行程序的性能所以hibernate出现了缓存机制,这样hibernate在进行数据读取时会先从一级缓存中查找如果没有则查找二级缓存如果还没有就会访问数据库。和CPU缓存机制类型hibernate缓存中的数据也会根据特定机制进行更新。

What:

hibernate的缓存也分为一级和二级

       一级缓存也称Session级缓存——

           1、  使用session控制,生命周期同session;所以当前session关闭后,缓存就没了

           2、  只能在当前线程中使用,不同的session间不能共享缓存数据

      二级缓存也称sessionFactory级缓存或进程级缓存——

           1、  使用sessionFactory控制,生命周期同sessionFactory

           2、  在当前进程中使用

       共同特点:只缓存实体对象,如果使用HQL查询普通属性不会缓存。具体的意思可以从实例中体会。

How:

         首先是一级缓存的使用:可分为查询实体和查询个别属性

         查询实体:

                   load或get查询一个实体:               

    /*** 在同一个session中发出两次load查询*/public void testLoad() {Sessionsession = null;try {session= HibernateUtils.getSession();session.beginTransaction();Studentstudent = (Student)session.load(Student.class, 1);System.out.println("student.name="+ student.getName());//不会发出查询语句,load使用缓存student= (Student)session.load(Student.class, 1);System.out.println("student.name="+ student.getName());session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}    

         执行完毕发现只发出一条查询语句,说明在第二次进行查询时session是从自己的缓存中获取的数据而不是从库中获取的。测试get方法和load方法是一样的。load和get方法的区别在于load默认是支持延迟加载的。


         list或iterate查询实体集:

   /*** 在同一个session中发出两次iterate查询,查询实体对象*/public void testIterate () {Sessionsession = null;try {session= HibernateUtils.getSession();session.beginTransaction();Iteratoriter = session.createQuery("from Student swhere s.id<5").iterate();while (iter.hasNext()) {Studentstudent = (Student)iter.next();System.out.println(student.getName());}System.out.println("--------------------------------------");//它会发出查询id的语句,但不会发出根据id查询学生的语句,因为iterate使用缓存iter= session.createQuery("from Student swhere s.id<5").iterate();while (iter.hasNext()) {Studentstudent = (Student)iter.next();System.out.println(student.getName());}session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}} </span>
执行结果如下:


     

        第一次查询时iterate会发出1条查询所有id的语句,然后在打印student的name时发出n条根据id查询详细信息的语句一共N+1条。而第二次查询时只发出一条查询id的语句,其他的数据是从session的缓存中获取的。


使用list在同意session中查询实体集,发出的查询语句如下:会发出两条查询语句

      

        出现如上的结果是不是说明使用iterate查询的结果才会放到session的缓存中而list的结果不会放到缓存中呢?看下面一个实例

   /*** 在同意session中先使用list,然后使用iterate进行查询*/public void testListIterate () {Sessionsession = null;try {session= HibernateUtils.getSession();session.beginTransaction();Liststudents = session.createQuery("select s fromStudent s where s.id<5").list();for (int i=0;i<students.size(); i++) {Studentstudnet = (Student)students.get(i);System.out.println(studnet.getName());}System.out.println("----------------------------------");Iteratoriter = session.createQuery("from Student swhere s.id<5").iterate();while (iter.hasNext()) {Studentstudent = (Student)iter.next();System.out.println(student.getName());}session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}    </span>

打印出的查询语句如下:

       

        上图中我们看到在使用iterate进程查询时没有发出N+1条语句,只发出了查询所有id的语句,结合两个例子说明list查出的结果会放到session的缓存中但是list本身的查询不会直接使用缓存中的数据,还是在此查询数据库。

 

查询普通属性:

       使用iterate查询某个普通属性,代码实例如下——

   /*** 在同一个session中发出两次iterate查询,查询普通属性*/public void testCache4() {Sessionsession = null;try {session= HibernateUtils.getSession();session.beginTransaction();Iteratoriter = session.createQuery("select s.namefrom Student s where s.id<5").iterate();while (iter.hasNext()) {Stringname = (String)iter.next();System.out.println(name);}System.out.println("--------------------------------------");//iterate查询普通属性,一级缓存不会缓存,所以发出查询语句//一级缓存是缓存实体对象的iter= session.createQuery("select s.namefrom Student s where s.id<5").iterate();while (iter.hasNext()) {Stringname = (String)iter.next();System.out.println(name);}session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}}    

       以上代码执行观察结果发现会发出两条查询语句,这说明只查询普通属性时session是不会进行缓存的。


一级缓存的生命周期:

/*** 在两个session中发load查询*/public void testCache5() {Sessionsession = null;try {session= HibernateUtils.getSession();session.beginTransaction();Studentstudent = (Student)session.load(Student.class, 1);System.out.println("student.name="+ student.getName());session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}try {session= HibernateUtils.getSession();session.beginTransaction();Studentstudent = (Student)session.load(Student.class, 1);//会发出查询语句,session间不能共享一级缓存数据//因为他会伴随着session的消亡而消亡System.out.println("student.name="+ student.getName());session.getTransaction().commit();}catch(Exception e) {e.printStackTrace();session.getTransaction().rollback();}finally {HibernateUtils.closeSession(session);}
}    

执行打印出的查询语句如下:

       

        发出两条查询语句和在第一个测试中使用同一个session只发一条查询语句是有差别的,这说明了一级缓存的生命周期是和session一致的,session关闭缓存就会消失。

 

小结:

         本篇博客介绍了通过操作系统的缓存机制映射到hibernate的缓存机制,发现它俩的思想是一样的。

         通过几个实例发现get/load/iterate/list在查询实体时都是支持一级缓存的,而且一级缓存的生命周期和session是一致的,当session关闭当前session中的缓存就会消失。下篇博客通过几个代码实例分析一下二级缓存及一级和二级缓存之间的关系。

这篇关于hibernate缓存学习之【一级缓存】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1105856

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个