题目
介绍 MyBatis 的一级缓存和二级缓存
答案
@[toc]
---
## 一级缓存
**MyBatis 一级缓存的生命周期和 SQLSession 一致**
每个 SQLSession 中持有了 Executor,每个 Executor 中有一个 Cache(其实就是一个没有容量限制的 **Map**)。当用户发起查询时,MyBatis 根据当前执行的语句生成 `MappedStatement`,在 Cache 进行查询,如果缓存命中的话,直接返回结果给用户,如果缓存没有命中的话,查询数据库,结果写入 `Cache`,最后返回结果给用户

`Cache`: MyBatis 中的 Cache 接口,提供了和缓存相关的最基本的操作,如下图所示:

有若干个实现类,使用**装饰器模式**互相组装,提供丰富的操控缓存的能力,部分实现类如下图所示:

`BaseExecutor` 成员变量之一的 `PerpetualCache`,是对 Cache 接口最基本的实现,其实现非常简单,内部持有 HashMap,对一级缓存的操作实则是对 HashMap 的操作。如下代码所示:
```java
public class PerpetualCache implements Cache {
private String id;
private Map<Object, Object> cache = new HashMap<Object, Object>();
```
## 二级缓存
**如果多个 SQLSession 之间需要共享缓存,则需要使用到二级缓存。开启二级缓存后,会使用 `CachingExecutor` 装饰 Executor**,进入一级缓存的查询流程前,先在 CachingExecutor 进行二级缓存的查询,具体的工作流程如下所示

二级缓存开启后,同一个 namespace 下的所有操作语句,都影响着同一个 Cache,即**二级缓存被多个 SQLSession 共享,是一个【全局的变量】**。
