文档章节

mybatis缓存机制详解(一)——Cache

拉风小野驴
 拉风小野驴
发布于 2016/02/24 10:45
字数 1253
阅读 4.6K
收藏 8

缓存概述

在mybatis中,缓存的功能由根接口Cache(org.apache.ibatis.cache.Cache)定义。整个体系采用装饰器设计模式,数据存储和缓存的基本功能由PerpetualCache(org.apache.ibatis.cache.impl.PerpetualCache)永久缓存实现,然后通过一系列的装饰器来对PerpetualCache永久缓存进行缓存策略等方便的控制。如下图:

用于装饰PerpetualCache的标准装饰器共有8个(全部在org.apache.ibatis.cache.decorators包中):

1.FifoCache:先进先出算法,缓存回收策略

2.LoggingCache:输出缓存命中的日志信息

3.LruCache:最近最少使用算法,缓存回收策略

4.ScheduledCache:调度缓存,负责定时清空缓存

5.SerializedCache:缓存序列化和反序列化存储

6.SoftCache:基于软引用实现的缓存管理策略

7.SynchronizedCache:同步的缓存装饰器,用于防止多线程并发访问

8.WeakCache:基于弱引用实现的缓存管理策略

另外,还有一个特殊的装饰器TransactionalCache:事务性的缓存


正如大多数持久层框架一样,mybatis缓存同样分为一级缓存和二级缓存

一级缓存,又叫本地缓存,是PerpetualCache类型的永久缓存,保存在执行器中(BaseExecutor),而执行器又在SqlSession(DefaultSqlSession)中,所以一级缓存的生命周期与SqlSession是相同的

二级缓存,又叫自定义缓存,实现了Cache接口的类都可以作为二级缓存,所以可配置如encache等的第三方缓存。二级缓存以namespace名称空间为其唯一标识,被保存在Configuration核心配置对象中。如下:

public class Configuration {
    // ...
    protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection");
    // ...
}

每次构建SqlSessionFactory对象时都会创建新的Configuration对象,因此,二级缓存的生命周期与SqlSessionFactory是相同的。在创建每个MapperedStatement对象时,都会根据其所属的namespace名称空间,给其分配Cache缓存对象。


二级缓存对象的默认类型为PerpetualCache,如果配置的缓存是默认类型,则mybatis会根据配置自动追加一系列装饰器。

Cache对象之间的引用顺序为:

SynchronizedCache-->LoggingCache-->SerializedCache-->ScheduledCache-->LruCache-->PerpetualCache


所有的缓存对象的操作与维护都是由Executor器执行来完成的,一级缓存由BaseExecutor(包含SimpleExecutor、ReuseExecutor、BatchExecutor三个子类)负责维护,二级缓存由CachingExecutor负责维护。因此需要注意的是:配置了二级缓存不代表mybatis就会使用二级缓存,还需要确保在创建SqlSession的过程中,mybatis创建是CachingExecutor类型的执行器。

Executor中对Cache的具体操作逻辑,请点击mybatis核心组件详解——Executor


源码解读:

Cache接口:

package org.apache.ibatis.cache;

import java.util.concurrent.locks.ReadWriteLock;


/**
 * 缓存接口
 * 给缓存供应商的SPI(Service Provider Interface)
 * 一个Cache的实例将为名称空间被创建
 * Cache接口的实现类必须有一个具有String类型参数的构造方法,用于接收Cache对象的id,作为其唯一标识
 * 
 * mybatis将以namespace作为id调用这个构造函数创建对象
 * 
 * @author Administrator
 *
 */
public interface Cache {

	/**
	 * 获取缓存对象的唯一标识
	 * @return
	 */
	String getId();

	/**
	 * 保存key/value到缓存对象中
	 * key可以是任何对象,但一般是CacheKey对象
	 * value是查询结果,为List类型
	 * @param key
	 * @param value
	 */
	void putObject(Object key, Object value);

	/**
	 * 从缓存对象中获取key对应的value
	 * @param key
	 * @return
	 */
	Object getObject(Object key);

	/**
	 * 可选的方法,没有被核心框架调用,移除key对应的value
	 * @param key
	 * @return
	 */
	Object removeObject(Object key);

	/**
	 * 清空缓存
	 */
	void clear();

	/**
	 * 获取缓存对象中存储的键/值对的数量
	 * 可选的方法,没有被框架核心调用
	 */
	int getSize();

	/**
	 * 获取读写锁
	 * 可选的方法,从3.2.6起这个方法不再被框架核心调用
	 * 任何需要的锁,都必须由缓存供应商提供
	 * 
	 * @return A ReadWriteLock
	 */
	ReadWriteLock getReadWriteLock();

}

PerpetualCache永久缓存:

package org.apache.ibatis.cache.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;

import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheException;

/**
 * 永久缓存 Cache接口实现类
 * Cache接口只有这唯一一个基础实现,其他实现类全都是装饰模式持有另一个缓存对象
 * 
 * @author Administrator
 *
 */
public class PerpetualCache implements Cache {
	// 缓存对象的唯一标识
	private String id;
	// 对象内部维护的HashMap
	private Map<Object, Object> cache = new HashMap<Object, Object>();

	public PerpetualCache(String id) {
		this.id = id;
	}

	public String getId() {
		return id;
	}

	public int getSize() {
		return cache.size();
	}

	public void putObject(Object key, Object value) {
		cache.put(key, value);
	}

	public Object getObject(Object key) {
		return cache.get(key);
	}

	public Object removeObject(Object key) {
		return cache.remove(key);
	}

	public void clear() {
		cache.clear();
	}

	public ReadWriteLock getReadWriteLock() {
		return null;
	}

	public boolean equals(Object o) {
		if (getId() == null)
			throw new CacheException("Cache instances require an ID.");
		if (this == o)
			return true;
		if (!(o instanceof Cache))
			return false;

		Cache otherCache = (Cache) o;
		return getId().equals(otherCache.getId());
	}

	public int hashCode() {
		if (getId() == null)
			throw new CacheException("Cache instances require an ID.");
		return getId().hashCode();
	}

}

在mybatis中,PerpetualCache是唯一的Cache接口的基础实现。它内部维护一个HashMap,所有的缓存操作,其实都是对这个HashMap的操作。

其他Cache接口的实现类全部为装饰器,源码详解请点击mybatis缓存机制详解(二)——缓存装饰器

© 著作权归作者所有

拉风小野驴
粉丝 61
博文 24
码字总数 26595
作品 0
昌平
高级程序员
私信 提问
加载中

评论(1)

i
itxx2016
推荐国内最流行的ibatis、mybatis代码生成网站: fwjava.com
无需任何安装配置,直接在线生成,且十分规范好用.
现在,很多知名的互联网公司都在用它.
MyBatis实战(三)-二级缓存原理解析

MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能。本文将全面分析MyBatis的二级缓存的设计原理。 1.MyBatis的缓存机制整体设计以及二级缓存的工...

芥末无疆sss
2018/10/07
0
0
【持久化框架】Mybatis与Hibernate的详细对比

前言 这篇博文我们重点分析一下Mybatis与Hibernate的区别,当然在前面的博文中我们已经深入的研究了Mybatis和Hibernate的原理。 Mybatis 【持久化框架】Mybatis简介与原理 【持久化框架】Spr...

sietai
2018/05/18
197
0
后台开发常问面试题集锦(问题搬运工,附链接)

Java基础问题 String的’+’的性能及原理 java之yield(),sleep(),wait()区别详解-备忘笔记 深入理解Java Stream流水线 抽象 & abstract关键字 Java final 修饰符知识点总结(必看篇) Java中的...

大黄有故事
2017/11/18
0
0
《深入理解mybatis原理》 MyBatis的二级缓存的设计原理

[+] MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能。本文将全面分析MyBatis的二级缓存的设计原理。 1.MyBatis的缓存机制整体设计以及二级缓存...

嘻哈开发者
2016/06/28
253
0
MyBatis框架——二级缓存-整合ehcache 缓存框架

1.加入ehcache包 ehcache-core-2.6.5.jar和mybatis-ehcache-1.0.2.jar 一个是ehcache自己的,一个是和mybatis的整合包 2.整合ehcache 配置mapper中cache中的type为ehcache对cache接口的实现类...

望崖
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

java面向对象编程3(8) 之 BeanUtils工具类

BeanUtils 一. 引言&概述&入门使用 BeanUtils可以让我们更方便快捷地 封装JavaBean数据。 例如可以用在带参构造, Set方法 , 反射。 入门使用: 导入jar包: public static void main(String[]...

煌sir
17分钟前
7
0
python 文件读写with open模式

模式 可做操作 若文件不存在 是否覆盖 r 只能读 报错 - r+ 可读可写 报错 是 w 只能写 创建 是 w+  可读可写 创建 是 a   只能写 创建 否,追加写 a+ 可读可写 创建 否,追加写 例子: wi...

好大一条鱼
17分钟前
3
0
动画:一篇文章快速学会桶排序

内容介绍 桶排序简介 前面学过计数排序,计数排序是一个非基于比较的排序算法,它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)。 所谓桶就是存放多个数据的容器,桶排序也是非...

表哥动画学编程
19分钟前
9
0
五行代码实现千万类别分类网络,飞桨大规模分类库揭秘

“桃花一簇无开主,可爱深红爱浅红。 黄四娘家花满蹊,千朵万朵压枝低。 留连戏蝶时时舞,自在娇莺恰恰啼。” 春天来了,经过一个冬天的“窖藏”,按耐不住的小伙伴纷纷行动了起来,踏一踏满...

飞桨PaddlePaddle
30分钟前
3
0
hadoop8天课程——第三天,MapReduce详解

MR擅长处理离线的文本文件。MR+yarn将简单的运算逻辑很方便的拓展到海量数据背景下运行分布式程序逻辑。 如果自己来写分布式程序的话,那么首先会面临一个问题,如何将我的计算逻辑分发到其他...

jingmamour
37分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部