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

hibernate二级缓存(二)二级缓存实现原理简单剖析hibernate二级缓存(一)二级缓存的实现原理在前面我们将过hibernate二级缓存类似于一个插件,将缓存的具体实现分离,缓存的具体实现是通过hibernate.cache.region.factory_class参数配置指定。1.hibernate二级缓存结构hibernate二级缓存涉及到如下几个重要的接口:RegionFactoryDomainDataRegionEnt…

大家好,又见面了,我是你们的朋友全栈君。

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 {
	//生成缓存key
	Object generateCacheKey(
			Object id,
			EntityPersister rootEntityDescriptor,
			SessionFactoryImplementor factory,
			String tenantIdentifier);
	//获取缓存key
	Object 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二级缓存。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/142272.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • python mkv转mp4,如何将mkv格式转换成mp4视频呢

    python mkv转mp4,如何将mkv格式转换成mp4视频呢在日常生活中都会使用到MKV视频文件的。MKV视频文件主要是视频文件、音频文件和字幕压制的。MKV视频一般在网上都是可以直接下载的。各种种子和磁链下载的也基本都是MKV视频。但有时可能会碰到视频播放错误。无法播放或者不支持文件播放的。一般都是可以通过转换视频格式修改的。那今天就教大家怎么将mkv格式转换成mp4格式吧。1、首先点击下方的立即下载按钮然后弹出下载迅捷视频转换器的下载框。下载打开之后,…

    2022年10月16日
  • Java正则匹配空格_正则表达式允许空格

    Java正则匹配空格_正则表达式允许空格举个例子Booleanxx=Pattern.matches(“^[a-zA-Z0-9\\s]*$”,”801TampinesAve4Singapore520801sss1″);匹配结果是false在众多正则表达式的教程中,对于\s的解释都是匹配空格。但在java中,\s不能对他们全部进行匹配。半角空格:“”.Unicode编码为:\u0020可以通过正则表达式中的\s进行匹配全角空格:“ ”Unicode编码为:\u3000不能通过正则表达式中的\s…

  • 新的博客-随记地址webooxx.com[通俗易懂]

    新的博客-随记地址webooxx.com[通俗易懂]虽然博客还没有完工,但是开了一个新的随记地址。webooxx.comMarkdocsOnline。是在百度的BAE上实现的,但是想弄到SAE上去,不过搞不定SAE的REWRITE,话说,其实我连本机

  • Python图像处理之小波去噪

    Python图像处理之小波去噪在此前的文章中,我们讨论了在Python中利用pywt包提供的API对图像做小波分解的基本方法。小波变换在图像处理中的一个具体应用就是平滑去噪。后续我们还会从原理上讨论如何利用小波变换来设计图像去噪算法。但在此之前,本文将主要演示,利用Python中已有的API进行图像小波去噪的方法及效果

  • 10240

    10240一个特殊的日子

  • java属于什么语言_java是什么语言 ?是什么系统?

    java属于什么语言_java是什么语言 ?是什么系统?一开始了解计算机这个专业,大家都会经常性听到Java这一词语,那么大家有真正的了解什么是Java吗?Java是属于什么语言呢?JAVA语言,其实是混合型的一种语言,Java语言是一个支持网络计算的面向对象程序设计语言。Java语言吸收了Smalltalk语言和C++语言的优点。下面来介绍一些Java的主要特征:1)Java语言是简单的。Java语言的语法与C语言和C++语言相似,这让很多程序员可…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号