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

相关文章

MyBatis延迟加载与多级缓存全解析

《MyBatis延迟加载与多级缓存全解析》文章介绍MyBatis的延迟加载与多级缓存机制,延迟加载按需加载关联数据提升性能,一级缓存会话级默认开启,二级缓存工厂级支持跨会话共享,增删改操作会清空对应缓... 目录MyBATis延迟加载策略一对多示例一对多示例MyBatis框架的缓存一级缓存二级缓存MyBat

前端缓存策略的自解方案全解析

《前端缓存策略的自解方案全解析》缓存从来都是前端的一个痛点,很多前端搞不清楚缓存到底是何物,:本文主要介绍前端缓存的自解方案,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、为什么“清缓存”成了技术圈的梗二、先给缓存“把个脉”:浏览器到底缓存了谁?三、设计思路:把“发版”做成“自愈”四、代码

Java 缓存框架 Caffeine 应用场景解析

《Java缓存框架Caffeine应用场景解析》文章介绍Caffeine作为高性能Java本地缓存框架,基于W-TinyLFU算法,支持异步加载、灵活过期策略、内存安全机制及统计监控,重点解析其... 目录一、Caffeine 简介1. 框架概述1.1 Caffeine的核心优势二、Caffeine 基础2

Redis高性能Key-Value存储与缓存利器常见解决方案

《Redis高性能Key-Value存储与缓存利器常见解决方案》Redis是高性能内存Key-Value存储系统,支持丰富数据类型与持久化方案(RDB/AOF),本文给大家介绍Redis高性能Key-... 目录Redis:高性能Key-Value存储与缓存利器什么是Redis?为什么选择Redis?Red

React 记忆缓存的三种方法实现

《React记忆缓存的三种方法实现》本文主要介绍了React记忆缓存的三种方法实现,包含React.memo、useMemo、useCallback,用于避免不必要的组件重渲染和计算,感兴趣的可以... 目录1. React.memo2. useMemo3. useCallback使用场景与注意事项在 Re

Docker多阶段镜像构建与缓存利用性能优化实践指南

《Docker多阶段镜像构建与缓存利用性能优化实践指南》这篇文章将从原理层面深入解析Docker多阶段构建与缓存机制,结合实际项目示例,说明如何有效利用构建缓存,组织镜像层次,最大化提升构建速度并减少... 目录一、技术背景与应用场景二、核心原理深入分析三、关键 dockerfile 解读3.1 Docke

使用Spring Cache本地缓存示例代码

《使用SpringCache本地缓存示例代码》缓存是提高应用程序性能的重要手段,通过将频繁访问的数据存储在内存中,可以减少数据库访问次数,从而加速数据读取,:本文主要介绍使用SpringCac... 目录一、Spring Cache简介核心特点:二、基础配置1. 添加依赖2. 启用缓存3. 缓存配置方案方案

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

Java实现本地缓存的四种方法实现与对比

《Java实现本地缓存的四种方法实现与对比》本地缓存的优点就是速度非常快,没有网络消耗,本地缓存比如caffine,guavacache这些都是比较常用的,下面我们来看看这四种缓存的具体实现吧... 目录1、HashMap2、Guava Cache3、Caffeine4、Encache本地缓存比如 caff

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.