MyBatis入门 – 缓存机制
1.查询缓存
1.1 查询缓存介绍
MyBatis提供两层查询缓存层,用于降低数据库压力,提高性能,框架如下:
1.2 一级缓存
1.2.1 介绍
一级缓存为SQLSession级别缓存。在执行数据查询时,需要构造SQLSession对象,并用于缓存数据。而一级缓存则是在同一个SQLSession中进行。当SQLSession首次执行时,数据库会将查询到的数据写入缓存中,第二次查询时则直接从该缓存中获取数据。一级缓存同时也是MyBatis默认缓存。
一级缓存只针对同一个SQLSession。在参数和SQL完全一样的情况下,我们使用同一个SQLSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SQLSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SQLSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
1.2.2 生命周期
对MyBatis进行不同的操作时一级缓存的生命周期也不同,以下是常见的四种生命周期
- MyBatis开启一个数据库会话时会创建一个SQLSession对象,其中包含一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象包括PerpetualCache对象也一并释放掉。
- 若SQLSession调用close()方法,将会释放缓存中的PerpetualCache对象,此时以及缓存不可用。
- 若SQLSession调用clearCache()方法,会清空PerpetualCache对象中的数据,但是该对象仍可使用。
- SQLSession中执行了任何一个update操作(update()、delete()、insert()) 都会清空PerpetualCache对象的数据,但是该对象可以继续使用。
1.2.3 相同查询的判断方式
若满足以下条件则是完全相同的查询
- 传入的statementId。
- 查询时要求的结果集中的结果范围。
- 本次查询所产生的最终要传递给JDBC java.sql.Preparedstatement的Sql语句字符串。
- 传递给java.sql.Statement要设置的参数值
1.3 二级缓存
1.3.1 介绍
二级缓存是Application层的特别缓存,即Mapper缓存。多个SQLSession操作同一个Mapper的SQL语句,多个SQLSession操作数据库返回的数据将存储在二级缓存,同时,多个SQLSession可以共用二级缓存。
二级缓存是多个SQLSession共享的,其作用域是mapper的同一个namespace,不同的SQLSession两次执行相同namespace下的SQL语句且向SQL中传递参数也相同即最终执行相同的SQL语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。
sqlSessionFactory层面上的二级缓存默认是不开启的,二级缓存的开启需要进行配置,实现二级缓存的时候,MyBatis要求返回的POJO必须是可序列化的。 也就是要求实现Serializable接口,配置方法很简单,只需要在映射XML文件配置就可以开启缓存。
2 缓存工作原理
2.1 一级缓存
2.1.1 工作原理
以id查询用户信息的一级缓存工作原理如下:
如果SQLSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
2.1.2 应用
正式开发,是将MyBatis和spring进行整合开发,事务控制在service中。一个service方法中包括很多mapper方法调用。
service{
//开始执行时,开启事务,创建SqlSession对象
//第一次调用mapper的方法findUserById(1)
//第二次调用mapper的方法findUserById(1),从一级缓存中取数据
//aop控制 只要方法结束,sqlSession关闭 sqlsession关闭后就销毁数据结构,清空缓存
Service结束sqlsession关闭
}
2.2 二级缓存
2.2.1 工作原理
如果SQLSession去执行相同 mapper下sql,执行commit提交,清空该 mapper下的二级缓存区域的数据。
二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。数据类型仍然为HashMap
UserMapper有一个二级缓存区域(按namespace分,如果namespace相同则使用同一个相同的二级缓存区),其它mapper也有自己的二级缓存区域(按namespace分)。
每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。
2.2.2 应用
mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。
<setting name="cacheEnabled"value="true"/>
<!-- 全局配置参数,需要时再设置 -->
<settings>
<!-- 开启二级缓存 默认值为true -->
<setting name="cacheEnabled" value="true"/>
</settings>