Mybatis的一级缓存
Mybatis默认的一级缓存是SqlSession缓存,也就是说在同一个SqlSession中执行相同的SQL,只有第一次会去查询数据库,接下来再进行该查询都是从Mybatis的缓存中去获取的。当执行增删改操作时,Mybatis会清空SqlSession的缓存。
一级缓存除了有SqlSession级别,还有statement级别,如果需要更改缓存级别,可以在Mybatis的主配置文件(核心配置文件)中进行修改,当我们将级别设置为statement后就等于关闭了一级缓存:
1 | <settings> |
当localCacheScope=SESSION时,在同一个SqlSession中进行两次相同的查询:
1 |
|
1 | [main] DEBUG c.w.m.HusbandDao.findAllHusband - ==> Preparing: SELECT * FROM husband |
从打印信息可以看出,调用了两次查询但只执行了一次数据库查询,说明第二次查询是从缓存中进行读取的
当localCacheScope=STATEMENT时,重复进行上述测试结果为:
1 | [main] DEBUG c.w.m.HusbandDao.findAllHusband - ==> Preparing: SELECT * FROM husband |
这里进行了两次数据库查询,并没有进行缓存
Mybatis的二级缓存
一级缓存为local cache,二级缓存为cache。cache是跨session的,既在一个SqlSession中缓存的查询结果,在另外一个SqlSession中也是可以使用的,范围比一级缓存更大。
开启二级缓存需要进行以下几步操作,首先在主配置文件中将cacheEnabled设置为true:
1 | <settings> |
然后在需要使用二级缓存的mapper.xml文件中添加
1 | <mapper namespace="com.example.mapper.HusbandDao"> |
如果要让某个statement不进行二级缓存,就将该statement的useCache标签设置为false:
1 | <!--开启二级缓存之后,useCache默认为true--> |
实体类实现序列化接口,这样做的目的是二级缓存的存储介质多种多样,不一定要存储在内存中,可能会进行序列化存储在本地磁盘中:
1 |
|
二级缓存的工作机制:
- 在一个会话中查询数据,查询成功后当前会话会将数据放入一级缓存中,此时不同的会话还无法共享数据
- 如果当前会话关闭或者提交,该会话中的一级缓存就会被清空,并将一级缓存刷入二级缓存中
- 其他会话在进行数据查询时,会先从二级缓存中查询是否有数据,如果没有再在一级缓存中查询,如果还是没有则去数据库中查询
进行二级缓存的测试:
1 |
|
1 | [main] DEBUG com.woniuxy.mapper.HusbandDao - Cache Hit Ratio [com.woniuxy.mapper.HusbandDao]: 0.0 |
从上述日志信息可以看出,sqlSession1在执行第一次查询时,由于一级缓存二级缓存中都没有数据,所以去数据库中查询。在sqlSession1关闭之后,sqlSession2进行了同样的查询,此时二级缓存中是有数据的,所以直接从缓存中获取数据。
###