(六)Hibernate的二级缓存

二级缓存简介

 

1
2
3
4
二级缓存是一个可插拔的缓存插件,由SessionFactory管理,是进程范围的缓存。
二级缓存有可能出现并发问题,因此需要采用适当的并发访问策略。
该策略为缓存中的数据提供了事务隔离级别。。
Hibernate还提供了查询缓存,依赖于二级缓存。

 

 

二级缓存中存放什么?  

 

1
2
3
4
5
6
7
8
9
10
11
符合以下条件的数据适合存放在二级缓存中
-很少被修改的数据
-不是很重要的数据,允许偶然出现的并发问题
-参考数据(指供应用程序参考的常量数据)
 
以下数据不适合存放到二级缓存中
-经常被修改的数据
-财务数据,绝对不允许出现并发文日
-与其他应用共享的数据
 
二级缓存中缓存的并不是对象,而是对象的散装数据。

常用二级缓存插件

 

1
2
3
4
5
6
7
8
9
二级缓存是可配置的插件,Hibernate允许选用以下的缓存插件
 
    -EHCache:可作为进程范围内的缓存。存放数据的物理介质可以是硬盘或者内存,支持hibernate的查询缓存。
 
    -OSCache:可作为进程范围内的缓存,存放数据的物理介质可以是硬盘或者内存,支持hibernate的查询缓存,提供了丰富的缓存数据过期策略。
 
    -SwarmCache:可作为集群范围内的缓存,不支持Hibernate的查询缓存。
 
    -JBossCache:可作为集群范围内的缓存,支持事务并发访问策略。支持Hibernate的查询缓存。

 

二级缓存的事务隔离级别

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
transactional(事务型):
    仅在受管理的环境中适用
    提供Repeatable Read事务隔离级别
    适用经常被读,很少修改的数据
    可以防止脏读和不可重复读的并发问题
    缓存支持事务,发生异常的时候,缓存也能够回滚
read-write(读写型);
    提供Read Committed事务隔离级别
    在非集群的环境中适用
    适用经常被读,很少修改的数据
    可以防止脏读
    更新缓存的时候会锁定缓存中的数据
nonstrict-read-write(非严格读写型):
    适用极少被修改,偶尔允许脏读的数据(两个事务同时修改数据的情况很少见)
    不保证缓存和数据库中数据的一致性
    为缓存数据设置很短的过期时间,从而尽量避免脏读
    不锁定缓存中的数据
read-only(只读型):
    适用从来不会被修改的数据(如参考数据)
    在此模式下,如果对数据进行更新操作,会有异常
    事务隔离级别低,并发性能高
    在集群环境中也能完美运作

 

这里写图片描述

为了把这些第三方缓存插件集成到Hibernate中,Hibernate提供了org.hibernate.cache.CacheProvider接口 
它是缓存插件与Hibernate之间的适配器。Hibernate为以上四个缓存插件提供了内置的适配器实现类。 
如果需要使用其他的缓存插件,只需要为这个插件提供实现了接口的类即可。

  

 

使用二级缓存

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
配置二级缓存
    1.打开二级缓存
    2.选择需要使用的二级缓存的持久化类,设置二级缓存的并发访问策略。
    3.选择合适的缓存插件,配置缓存插件的配置文件。
 
    我们演示使用EHCache插件
    1)先导包,Hibernate包中已经为我们准备好了  将hibernate-release-5.1.7.Final\lib\optional\ehcache目录下的jar包导入
    2)在hibernate.cfg.xml中配置使用二级缓存
        配置使用二级缓存       
      <property name="hibernate.cache.use_second_level_cache">true</property>
 
    3)配置使用EHcache的实现类
      配置文件中的类名为org.hibernate.cache.internal.EhCacheRegionFactory,但是出错。把internal去掉就行了
      <property name="hibernate.cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property>

 

  

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
Hibernate允许配置类和集合上设置二级缓存。还可以设置查询缓存
 
        (一)在类上设置二级缓存   
        在hibernate.cfg.xml的<mapping>元素后面配置
        <!--usage设置隔离级别,class设置哪个类-->
        <class-cache usage="read-only" class="com.cad.domain.Customer"/>
 
        (2)我们测试一下是否对象存到了二级缓存
        public class Demo {
 
            private Session session;
 
            @Test
            public void test() {
                //读取配置文件
                Configuration conf=new Configuration().configure();
 
                //根据配置创建factory
                SessionFactory sessionfactory=conf.buildSessionFactory();
                session = sessionfactory.openSession();
                 Transaction ts=session.beginTransaction();
                 //获取对象,打印select语句
                 Customer c1=session.get(Customer.class, 7);
                 //清除一级缓存
                 session.clear();
                 //再获取对象,没有打印select语句,说明对象存放在了二级缓存中
                 Customer c2=session.get(Customer.class, 7);
                ts.commit();
                session.close();
                sessionfactory.close();
            }
 
        }
 
 
    (二) 在集合上设置二级缓存区
        要把集合中的对象也给设置二级缓存区。
          <class-cache usage="read-only" class="com.cad.domain.Customer"/>
          <class-cache usage="read-only" class="com.cad.domain.Order"/>
          <!--collection设置对象中的集合-->
          <collection-cache usage="read-only" collection="com.cad.domain.Customer.orders"/>
 
 
          我们测试一下
             public class Demo {
 
                private Session session;
 
                @Test
                public void test() {
                    //读取配置文件
                    Configuration conf=new Configuration().configure();
 
                    //根据配置创建factory
                    SessionFactory sessionfactory=conf.buildSessionFactory();
                    session = sessionfactory.openSession();
                     Transaction ts=session.beginTransaction();
                     //打印select语句
                     Customer c1=session.get(Customer.class, 7);
                     for(com.cad.domain.Order o:c1.getOrders()){
                         System.out.println(o.getName());
                     }
                     //清空缓冲区
                     session.clear();
                     //再查找,不打印,说明集合中的对象都被放到了二级缓存中
                     Customer c2=session.get(Customer.class, 7);
                     for(com.cad.domain.Order o:c2.getOrders()){
                         System.out.println(o.getName());
                     }
                    ts.commit();
                    session.close();
                    sessionfactory.close();
                }
 
            }

  

  

 

  

 

posted @   跃小云  阅读(179)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示