Hibernate 一级缓存和二级缓存

2024-04-01 15:18

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

一级缓存[Session级别]

一个Session做了一个查询操作,它会把这个操作的结果放在一级缓存中,如果短时间内这个session(一定要同一个session)又做了同一个操作,那么hibernate直接从一级缓存中拿,而不会再去连数据库,取数据

  1. 每个事务都有单独的第一级缓存进程范围或集群范围

    缓存被同一个进程或集群范围内的所有事务共享并发访问策略由于每个事务都拥有单独的第一级缓存,不会出现并发问题
    
  2. 处于一级缓存中的对象永远不会过期

    除非应用程序显式清空缓存或者清除特定的对象,必须提供数据过期策略,如基于内存的缓存中的对象的最大数目,允许对象处于缓存中的最长时间,以及允许对象处于缓存中的最长空闲时间物理存储介质内存内存和硬盘。
    
  3. 对象的散装数据首先存放在基于内存的缓存中,当内存中对象的数目达到数据过期策略中指定上限时,就会把其余的对象写入基于硬盘的缓存中。

  4. save、update、saveOrupdate、load、list、iterate、lock会向一级缓存存放数据

  5. Session为应用程序提供了两个管理缓存的方法:

         evict(Object obj):从缓存中清除参数指定的持久化对象。 clear():清空缓存中所有持久化对象。
    

query.list()和query.iterate()

query.list()会一次性查询出所有的对象并且放入一级缓存中

@Testpublic void testQueryList() throws Exception {Session session = HibernateUtils.getSession();Query query = session.createQuery("from Student");//把查询出的所有学生信息放入一级缓存List<Student> list = (List<Student>) query.list();//此时再查询会直接从一级缓存中取Student student = session.get(Student.class,0);}

输出结果

Hibernate: 
selectstudent0_.id as id1_0_,student0_.phone as phone2_0_,student0_.postcode as postcode3_0_,student0_.birth as birth4_0_,student0_.c_id as c_id7_0_,student0_.gender as gender5_0_,student0_.name as name6_0_ 
fromstudent student0_
Hibernate: selectclasses0_.c_id as c_id1_1_0_,classes0_.c_name as c_name2_1_0_ fromclass classes0_ whereclasses0_.c_id=?

query.iterate()会查询出所有对象的id 当要获取某个对象时再去数据库中取

@Testpublic void testIterate() throws Exception {Session session = HibernateUtils.getSession();Query query = session.createQuery("from Student ");//查询出所有student的idIterator<Student> iterate = query.iterate();//当要获取某个student对象时 再去数据库取while (iterate.hasNext()){System.out.println(iterate.next());}}

输出结果

Hibernate: 
selectstudent0_.id as col_0_0_ 
fromstudent student0_
Hibernate: selectstudent0_.id as id1_0_0_,student0_.phone as phone2_0_0_,student0_.postcode as postcode3_0_0_,student0_.birth as birth4_0_0_,student0_.c_id as c_id7_0_0_,student0_.gender as gender5_0_0_,student0_.name as name6_0_0_,classes1_.c_id as c_id1_1_1_,classes1_.c_name as c_name2_1_1_ fromstudent student0_ left outer joinclass classes1_ on student0_.c_id=classes1_.c_id wherestudent0_.id=?
Student{id=0, name='heqianqian', gender='female', birth=2017-04-30, address=Address{postCode='335400', phone='10086'}

如果我们需要在一个session当中要两次查询出很多对象,可以第一次使用List将对象信息放入一级缓存,第二次使用iterate获取所有对象的id 再根据id去一级缓存中获取数据

注意:

一级缓存不需要配置,就可以使用,它本身没有保护机制,所以我们程序员要考虑这个问题,我们可以同 evict 或者 clear来清除session缓存中对象. evict 是清除一个对象,clear是清除所有的sesion缓存对象

② session级缓存中对象的生命周期, 当session关闭后,就自动销毁.

二级缓存[SessionFactory级别]

使用hibernate二级缓存,我们首先需要对其进行配置,配置步骤如下:

1.添加jar包
hibernate并没有提供相应的二级缓存的组件,常用的二级缓存包是EHcache

<!--cache--><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-ehcache</artifactId><version>5.2.10.Final</version></dependency><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId><version>2.10.2</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency>

2.在hibernate配置文件中开启二级缓存总开关 并且配置ehcache配置文件的位置

 <!-- 开启二级缓存 --><property name="hibernate.cache.use_second_level_cache">true</property><!-- 二级缓存的提供类 在hibernate4.0版本以后我们都是配置这个属性来指定二级缓存的提供类--><property name="hibernate.cache.region.factory_class">org.hibernate.cache.SingletonEhCacheRegionFactory</property><!-- 二级缓存配置文件的位置 --><property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property><!--如果是使用hibernate3的版本的话,那么二级缓存的提供类则要配置成这个:--><property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</property>

3.在ehcache.xml中配置缓存信息

<ehcache><!--指定数据在磁盘中的存储位置--><diskStore path="F:\ehcache"/><!--当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略--><defaultCache
            maxElementsInMemory="1000"maxElementsOnDisk="10000000"eternal="false"overflowToDisk="false"timeToIdleSeconds="120"timeToLiveSeconds="120"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"><!--必选参数1.maxElementsInMemory:在内存中缓存的element的最大数目2.maxElementsOnDisk:在磁盘上缓存的element的最大数目,若是0表示无穷大3.eternal:设定缓存的elements是否永远不过期如果为true,则缓存的数据始终有效如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断4.overflowToDisk:设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上--><!--可选参数1.timeToIdleSeconds:当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大2.timeToLiveSeconds:缓存element的有效生命期,默认是0.,也就是element存活时间无穷大3.diskSpoolBufferSizeMB:设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区4.diskPersistent:在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false5.diskExpiryThreadIntervalSeconds:磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作6.memoryStoreEvictionPolicy:当内存缓存达到最大,有新的element加入的时候,移除缓存中element的策略。默认是LRU(最近最少使用)可选的有LFU(最不常使用)和FIFO(先进先出)-->
</defaultCache>
</ehcache>

4.开启二级缓存

1)使用xml方式

<class name="com.hqq.bean.Student" table="student" schema="hibernate"><!--二级缓存一般设置为只读的 --><cache usage="read-only"/><id name="id" column="id"/><property name="name" column="name"/><property name="gender" column="gender"/><property name="birth" column="birth"/><!--<property name="address" column="address"/>--><component name="address" class="com.hqq.bean.Address"><property name="phone" column="phone"/><property name="postCode" column="postcode"/></component></class>

二级缓存的使用策略一般有这几种:read-only、nonstrict-read-write、read-write、transactional

2)使用注解的方式

@Entity
@Table(name = "student", schema = "hibernate")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)//表示开启二级缓存,并使用read-only策略
public class Student implements Serializable {

5.配置完毕 测试二级缓存是否开启

@Testpublic void test() throws Exception {Session session = HibernateUtils.getSession();Student student = session.get(Student.class, 0);System.out.println(student);session.close();Session session2 = HibernateUtils.getSession();Student student2 = session2.get(Student.class, 0);System.out.println(student2);}

测试结果

Hibernate: 
selectclasses0_.c_id as c_id1_1_0_,classes0_.c_name as c_name2_1_0_ 
fromclass classes0_ 
whereclasses0_.c_id=?Student{id=0, name='heqianqian', gender='female', birth=2017-04-30, address=Address{postCode='335400', phone='10086'}

注意:

  1. 二级缓存缓存的是对象 不会缓存属性
  2. 二级缓存不会缓存hql语句 需要配置:

hibernate.cfg.xml

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

Student类上添加@Cachable注解

@Entity
@Table(name = "student", schema = "hibernate")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)//表示开启二级缓存,并使用read-only策略
public class Student implements Serializable {

测试

@Testpublic void testHql() throws Exception {Session session = HibernateUtils.getSession();List<Student> list = session.createQuery("from Student ").setCacheable(true).list();Iterator<Student> students = (Iterator<Student>) list.iterator();while (students.hasNext()){System.out.println(students.next());}//session.close();Session session1 = HibernateUtils.getSession();List<Student> list1 = session.createQuery("from Student ").setCacheable(true).list();Iterator<Student> students1 = (Iterator<Student>) list1.iterator();while (students1.hasNext()){System.out.println(students1.next());}}

输出:

Hibernate: 
selectstudent0_.id as id1_0_,student0_.phone as phone2_0_,student0_.postcode as postcode3_0_,student0_.birth as birth4_0_,student0_.c_id as c_id7_0_,student0_.gender as gender5_0_,student0_.name as name6_0_ 
fromstudent student0_
Hibernate: selectclasses0_.c_id as c_id1_1_0_,classes0_.c_name as c_name2_1_0_ fromclass classes0_ whereclasses0_.c_id=?Student{id=0, name='heqianqian', gender='female', birth=2017-04-30, address=Address{postCode='335400', phone='10086'}Student{id=0, name='heqianqian', gender='female', birth=2017-04-30, address=Address{postCode='335400', phone='10086'}

参考文章:

http://www.cnblogs.com/xiaoluo501395377/p/3377604.html
http://blog.csdn.net/xlgen157387/article/details/40071651

这篇关于Hibernate 一级缓存和二级缓存的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

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. 缓存配置方案方案

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

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

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

java如何实现高并发场景下三级缓存的数据一致性

《java如何实现高并发场景下三级缓存的数据一致性》这篇文章主要为大家详细介绍了java如何实现高并发场景下三级缓存的数据一致性,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 下面代码是一个使用Java和Redisson实现的三级缓存服务,主要功能包括:1.缓存结构:本地缓存:使