# mybatis缓存


<!--more-->

## 一级缓存
一级缓存默认开启  
一级缓存是基于session的，执行插入、更新、删除等操作会清空缓存  
> 简单分析：  
> 1.sqlSession.getMapper(**Mapper.class); 生成mapper代理对象  
> 2.执行mapper方法的时候，调用代理对象的invoke方法，即MapperProxy中的invoke  
> 3.invoke方法中的execute方法通过各种判断，调用 sqlSession 接口中的方法  
> ![cache1](https://img.zhaojq.top/20260727184921219.png "cache1")  
> 4.sqlSession 中会调用 executor 执行器接口中的方法  
> > 1)先生成cacheKey   
> > 2)再query方法中，先尝试从缓存 localCache 中获取，如果没有，则从数据库中查询 queryFromDatabase  
> > ![cache2](https://img.zhaojq.top/20260727184921412.png "cache2")  
> > 3)queryFromDatabase 中将查询结果放入 localCache 中  
> > ![cache3](https://img.zhaojq.top/20260727184921626.png "cache3")  

## 二级缓存
二级缓存的原理和一级缓存原理一样，第一次查询，会将数据放入缓存中，然后第二次查询则会直接去缓存中取。  
但是一级缓存是基于sqlSession的，而二级缓存是基于mapper文件的namespace的，也就是说多个sqlSession可以共享一个mapper中的二级缓存区域，  
并且如果两个mapper的namespace相同，即使是两个mapper,那么这两个mapper中执行sql查询到的数据也将存在相同的二级缓存区域中
![cache4](https://img.zhaojq.top/20260727184921814.png "cache4")  

### 1.开启二级缓存
默认不开启，需要手动开启
```xml
<!-- sqlMapConfig.xml中 -->
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>
```
```xml
<!-- **Mappre.xml中
我们可以看到mapper.xml文件中就这么一个空标签，其实这里可以配置,PerpetualCache这个类是
mybatis默认实现缓存功能的类。我们不写type就使用mybatis默认的缓存，也可以去实现Cache接口
来自定义缓存 -->
<cache></cache>
```
看源码，我们发现，二级缓存其实也是一个Map
![cache5](https://img.zhaojq.top/20260727184922015.png "cache5")
![cache6](https://img.zhaojq.top/20260727184922204.png "cache6")

### 2.useCache和flushCache
- userCache 是用来设置是否禁用二级缓存，在statement中设置useCache=false可以禁用当前select语句的二级缓存
- flushCache="true”属性，默认情况下为true,即刷新缓存，如果改成false则不会刷新

### 3.二级缓存整合redis
- 引入依赖
    ```xml
    <dependency>
        <groupId>org.mybatis.caches</groupId>
        <artifactId>mybatis-redis</artifactId>
        <version>1.0.0-beta2</version>
    </dependency>
    ```
- **Mapper.xml
    ```xml
    <cache type="org.mybatis.caches.redis.RedisCache" />
    ```
- redis.properties
    ```properties
    redis.host=localhost
    redis.port=6379
    redis.connectionTimeout=5000
    redis.password=
    redis.database=0
    ```
  
> ps: 一级和二级缓存在单体应用时有用，在分布式、分库分表情况下，可以说很鸡肋，尤其二级缓存容易造成脏读现象，不建议使用



  


















