hibernate二级缓存(二)二级缓存实现原理简单剖析

在前面我们将过hibernate二级缓存类似于一个插件,将缓存的具体实现分离,缓存的具体实现是通过hibernate.cache.region.factory_class参数配置指定。本文只是对hibernate二级缓存的部分接口进行简单的解析,大致了解二级缓存的整体结构,二级缓存的内部实现很复杂,如要深究请阅读hibernate源码。

1. hibernate二级缓存结构

hibernate二级缓存涉及到如下几个重要的接口:

  • RegionFactory
  • DomainDataRegion
  • EntityDataAccess
  • StorageAccess

1.1 RegionFactory获取缓存的工厂,RegionFactory有如下几个重要的方法:

public interface RegionFactory extends Service, Stoppable {//初始化方法void start(SessionFactoryOptions settings, Map configValues) throws CacheException;boolean isMinimalPutsEnabledByDefault();//缓存策略AccessType getDefaultAccessType();String qualify(String regionName);default CacheTransactionSynchronization createTransactionContext(SharedSessionContractImplementor session) {return new StandardCacheTransactionSynchronization( this );}long nextTimestamp();default long getTimeout() {// most existing providers defined this as 60 seconds.return 60000;}DomainDataRegion buildDomainDataRegion(DomainDataRegionConfig regionConfig,DomainDataRegionBuildingContext buildingContext);QueryResultsRegion buildQueryResultsRegion(String regionName, SessionFactoryImplementor sessionFactory);TimestampsRegion buildTimestampsRegion(String regionName, SessionFactoryImplementor sessionFactory);
}
  • start 初始化RegionFactory
  • getDefaultAccessType 获得缓存策略,前面说过的CacheConcurrencyStrategy内部是基于AccessType
  • nextTimestamp 生成时间戳,用于时间戳缓存
  • buildDomainDataRegion 创建一个实体领域模型的Region,使用该对象来缓存实体,可以理解为实体缓存的holder
  • buildQueryResultsRegion 创建查询缓存
  • buildTimestampsRegion 创建时间戳缓存。时间戳缓存Region存放了对于查询结果相关的表进行插入, 更新或删除操作的时间戳。Hibernate 通过时间戳缓存Region来判断被缓存的查询结果是否过期

RegionFactory 是创建缓存的工厂,所有的缓存都是通过RegionFactory 来获取的,而RegionFactory 是在EnabledCaching构造方法中初始化的。RegionFactory 的初始化过程如下图所示:

sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();可以看到是在初始化sessionFactory的时候来初始化RegionFactory 。

1.2 DomainDataRegion缓存区域

DomainDataRegion可以理解为缓存的wraper或者holder。接口如下:

public interface DomainDataRegion extends Region {EntityDataAccess getEntityDataAccess(NavigableRole var1);NaturalIdDataAccess getNaturalIdDataAccess(NavigableRole var1);CollectionDataAccess getCollectionDataAccess(NavigableRole var1);
}

getEntityDataAccess 获得一个EntityDataAccess,对缓存的操作实际上是代理给EntityDataAccess,由EntityDataAccess来真正的管理缓存。

1.3 EntityDataAccess 缓存实际的访问者,用于管理对缓存实体数据的事务性和并发访问的协定

public interface EntityDataAccess extends CachedDomainDataAccess {//生成缓存keyObject generateCacheKey(Object id,EntityPersister rootEntityDescriptor,SessionFactoryImplementor factory,String tenantIdentifier);//获取缓存keyObject getCacheKeyId(Object cacheKey);//在查询后,是否将查询结果插入缓存boolean insert(SharedSessionContractImplementor session, Object key, Object value, Object version);//插入后是否更新缓存boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version);boolean update(SharedSessionContractImplementor session,Object key,Object value,Object currentVersion,Object previousVersion);boolean afterUpdate(SharedSessionContractImplementor session,Object key,Object value,Object currentVersion,Object previousVersion,SoftLock lock);
}

在上面的接口中我们并没有看到实际操作缓存的接口,那么EntityDataAccess 又是怎么访问和管理缓存的呢,下面来看一下EntityDataAccess 的接口继承和实现关系:

从上面的图我们可以看到EntityDataAccess 有一个抽象类,4个实现类。4个实现类分别对应了4中缓存访问类型,READ_ONLY,TRANSACTIONAL,READ_WRITE,NONSTRICT_READ_WRITE。抽象类AbstractEntityDataAccess实现了
EntityDataAccess 继承了AbstractCachedDomainDataAccess。AbstractCachedDomainDataAccess的部分代码如下:


AbstractCachedDomainDataAccess里面包含了一个DomainDataStorageAccess,DomainDataStorageAccess继承自StorageAccess,StorageAccess的接口如下:

public interface StorageAccess {/*** Get an item from the cache.*/Object getFromCache(Object key, SharedSessionContractImplementor session);/*** Put an item into the cache*/void putIntoCache(Object key, Object value, SharedSessionContractImplementor session);/*** Remove an item from the cache by key*/default void removeFromCache(Object key, SharedSessionContractImplementor session) {evictData( key );}/*** Clear data from the cache*/default void clearCache(SharedSessionContractImplementor session) {evictData();}/*** Does the cache contain this key?*/boolean contains(Object key);/*** Clear all data regardless of transaction/locking*/void evictData();/*** Remove the entry regardless of transaction/locking*/void evictData(Object key);/*** Release any resources.  Called during cache shutdown*/void release();
}

到这里我们终于发现了操作缓存的实际接口。而DomainDataStorageAccess接口是缓存操作必须实现的接口,ehchche的实现类是StorageAccessImpl。当然通过扩展该接口我们还可以将缓存放置到redis,memcache。

2. 缓存的初始化和调用

2.1 从上面的接口关系我们大致可以得到如下的一个缓存初始化关系链:

sessionFactory ----->EnabledCaching ----->RegionFactory ----->DomainDataRegion ----->EntityDataAccess ----->AbstractEntityDataAccess ----->AbstractCachedDomainDataAccess ----->StorageAccess

2.2 获取cache的调用栈


SessionImpl获取实体对象,然后通过一系列的调用,最终会落到AbstractCachedDomainDataAccess.get(SharedSessionContractImplementor session, Object key),前面已经说过该方法实际上是调用的DomainDataStorageAccess.getFromCache( key, session )。

3. 自定义hibernate缓存

通过前面的一系列分析,我们大致了解了hibernate缓存的一些重要的接口。如果要自定义hibernate缓存那么我们必须实现上面的这些接口。好在hibernate内部为实现了大多数的扩展,我们只需要扩展RegionFactory和DomainDataStorageAccess接口既可以自定义hibernate的二级缓存。
hibernate为实现RegionFactory提供了一个模版类RegionFactoryTemplate,我们直接通过实现该类和DomainDataStorageAccess,即可自定义hibernate二级缓存。

hibernate二级缓存(二)二级缓存实现原理简单剖析相关推荐

  1. 什么是缓存?Mybaits一级缓存和二级缓存分别是什么,区别是什么?缓存和缓冲区的区别是什么?

    目录 一.什么是缓存 二.缓存的好处及缺点 三. 存(cache)与缓冲(buffer)的主要区别 四.Mybaits中缓存分为什么? 1.一级缓存 1.2一级缓存失效 2.二级缓存(不建议使用) 3 ...

  2. 分布式缓存redis+本地缓存Caffeine:多级缓存架构在行情系统中的应用

    多级缓存架构在行情系统中的应用 一 为什么要有多级缓存 二 多级缓存架构 三 代码实现 @PreHeat 注解 CacheAspect 定时任务执行器PreheatTask LocalCacheSer ...

  3. 【组合数学】鸽巢原理 ( 鸽巢原理简单形式示例 4、5 )

    文章目录 一.鸽巢原理简单形式示例 4 二.鸽巢原理简单形式示例 5 一.鸽巢原理简单形式示例 4 假设有 333 个 777 位二进制数 , A:a1a2a3a4a5a6a7A : a_1a_2a_ ...

  4. 【组合数学】鸽巢原理 ( 鸽巢原理简单形式 | 鸽巢原理简单形式示例 1、2、3 )

    文章目录 一.鸽巢原理简单形式 二.鸽巢原理简单形式示例 1 三.鸽巢原理简单形式示例 2 四.鸽巢原理简单形式示例 3 一.鸽巢原理简单形式 鸽巢原理 : 将 n+1n + 1n+1 个物体 放到 ...

  5. Spring 框架之 AOP 原理深度剖析!|CSDN 博文精选

    作者 | GitChat 责编 | 郭芮 出品 | CSDN 博客 AOP(Aspect Oriented Programming)面向切面编程是 Spring 框架最核心的组件之一,它通过对程序结构 ...

  6. 细说Mybatis一级缓存、二级缓存以及mybatis获取mapper的面向接口编程思想(Mapper接口动态代理实现原理)(二)

    上一章和大家分享了Mybatis一级缓存和二级缓存,本章将继续和大家分享Mapper接口动态代理实现原理,按照国际惯例,先看源码,然后结合原理,写一个自己的小demo,从理论到实战,真正掌握面向接口编 ...

  7. hibernate之 一级缓存和二级缓存

    2019独角兽企业重金招聘Python工程师标准>>> 缓存 缓存的实现不仅需要作为物理介质的硬件,同时需要管理缓存的并发访问策略和过期策略的程序(软件).所以缓存通常是通过软件和硬 ...

  8. Hibernate之一级缓存和二级缓存

    1:Hibernate的一级缓存: 1.1:使用一级缓存的目的是为了减少对数据库的访问次数,从而提升hibernate的执行效率:(当执行一次查询操作的时候,执行第二次查询操作,先检查缓存中是否有数据 ...

  9. Hibernate 一级缓存,二级缓存,查询缓存

    概念: 1.什么是缓存呢? 缓存:是计算机领域的概念,它介于应用程序和永久性数据存储源之间. 缓存:一般人的理解是在内存中的一块空间,可以将二级缓存配置到硬盘.用白话来说,就是一个存储数据的容器.我们 ...

  10. Mybatis的一、二级缓存的原理与使用、禁止指定方法的二级缓存与刷新缓存、Mybatis整合Ehcache、二级缓存的使用场景与局限性-day03

    目录 第一节 Mybatis的缓存 1.1 Mybatis的缓存理解 1.2 一级缓存 原理 使用与测试 1.3 二级缓存 原理 使用与测试 禁用指定方法的二级缓存 刷新缓存 总结 1.4 整合ehc ...

最新文章

  1. react native初始化项目
  2. Goalng笔记——排序和查找
  3. Java刷新Jpanel_java – 刷新JPanel
  4. Struts2 中 Session 的使用
  5. 2012年软件开发者薪资调查报告
  6. 小型的搜索引擎设计_广州网站设计工作室-赛致信息科技
  7. 电脑怎么卸载软件干净_极客卸载,还你干净电脑
  8. python软件怎么打开画图_Python实现画图软件功能
  9. APICloud开源O2O商城源码
  10. 一个博士的悲情经历~失败的经验最美···小木虫上的系列精华帖(科研的、被科研的,共勉。转载,个人整理)
  11. 一个人不自信有多可怕?
  12. 读书《AB实验:科学归因与增长的利器》(刘玉凤)
  13. 问题:设计一个大学教师和学生管理程序, 教师包括 编号、姓名、职称和教研室 数据的输入输出; 大学生包括编号、姓名、性别、班号、英语、高等数学和数据结构三门课程成绩的输入输出和计算平均分; 研究生包
  14. 【机器人栅格地图】基于灰狼算法求解栅格地图路径规划及避障含Matlab源码
  15. 【Ruby on Rails全栈课程】4.1 点赞功能
  16. Python|做一个无线弹窗病毒
  17. SpringBoot集成Swagger2、Swagger2和Swagger3的区别Swagger的注解学习
  18. 关于mac12系统使用php(安装篇)
  19. ORACLE有EXCEL中trend函数,excel线性回归拟合线Trend函数是这样来使用的
  20. 手把手带你用next搭建一个完善的react服务端渲染项目(集成antd、redux、样式解决方案)

热门文章

  1. 【正点原子STM32连载】 第三十三章 光敏传感器实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
  2. 【SpringBoot】24、SpringBoot中实现数据字典
  3. python网络爬虫项目——翻译英文单词
  4. 大漠插件7.2137
  5. 三星note3官方固件rom包android4.4.2,三星N9005/Note3最新官方4.4.2系统刷机包官方root版本稳定纯净...
  6. 12万字 | 2021数据安全与个人信息保护技术白皮书(附下载)
  7. 提取source引擎.mdl模型,并转unity引擎.fbx
  8. 一文读懂TOGAF企业架构
  9. 操作系统高响应比优先调度算法模拟实验
  10. 51单片机c语言秒表,51单片机秒表C程序