一、缓存(Cache)
1、定义:缓存是一种用于存储数据的硬件设备或存储空间(缓存不是内存)。
2、作用:减轻数据库压力,提高查询性能
3、实现原理:将从数据库中查询出来的对象/记录在使用完后不直接销毁,而是将其存储在缓存中,当需要再次获取该对象时,不再通过向数据库执行SQL语句获取,而是直接从缓存中获取,因此减少了对数据库的查询次数,提高了数据库的性能。
二、一级缓存
1、作用域:同一个SqlSession对象
2、实现原理:在使用同一个SqlSession对象多次调用同一个Mapper方法且Mapper方法中包含参数在内的SQL语句完全相同时,第一次执行完毕会将数据库中查询到的数据写到缓存中,在第二次查询时如果不对缓存进行刷新且缓存没有超时,那么第二次执行完毕会从直接从缓存中获取数据不再从数据库中进行查询,提高了对数据库的查询效率。
3、特点:
- 当某个SqlSession对象结束时,该SqlSession对象的一级缓存也就不存在了。
- MyBatis在默认情况下一级缓存是开启
4、生命周期:
a、MyBatis在开启一个数据数据库会话时,会创建一个SqlSession对象,该SqlSession对象中会有一个Executor对象,Executor对象中会持有一个PerpetualCache对象。如果SqlSession对象调用了close()方法,会释放掉一级缓存PerpetualCache对象,该SqlSession对象的一级缓存将不可再用。
b、如果SqlSession对象调用了clearCache(),会清空PerpetualCache对象中的数据,但是一级缓存依旧可用。
c、SqlSession中执行任何一个update操作(update()、delete()、insert()),都会清空一级缓存中的数据,但是一级缓存依旧可用。
5、MyBatis一级缓存的工作模式
6、SqlSession对象中的clearCache()方法
作用:清空当前SqlSession对象中的一级缓冲中的数据
三、二级缓存
1、作用域:同一个namespace
2、实现原理:两个不同的SqlSession对象执行同一个namespace下的相同Mapper方法中的包含传递参数在内的完全相同的SQL语句时,第一个SqlSession对象在执行完后会将从数据库中查询到的数据写到二级缓存中,第二个SqlSession对象在执行SQL语句时会直接从二级缓存中获取数据,提高了查询效率
3、特点:
- MyBatis在默认情况下二级缓存是关闭的
- 在MyBatis中开启二级缓存需要在setting全局参数中进行配置
4、二级缓存详解
(1)二级缓存是SqlSessionFactory级别的,是更具Mapper中的namespace划分区域的,相同的namespace的Mapper查询的数据缓存在同一个区域,如果使用Mapper代理方法则每个Mapper的namespace都不同,此时可以理解为二级缓存根据Mapper来划分区域。
(2)每次执行select查询语句时会先在二级缓存区域进行查找,如果找不到才会从数据库中进行查询,并将查询到的数据写入缓存。
(3)MyBatis的内部存储缓存使用了一个HashMap,key的值是hashCode+sqlId+SQL语句,value的值为由查询结果映射生成的java对象。
(4)SqlSession对象执行insert、update、delete操作comit提交后会清空二级缓冲区域,防止脏读。
5、MyBatis二级缓存的工作模式
6、配置二级缓存
(1)第一步:启用二级缓存:在MyBatis核心配置文件mybatis.xml中添加指定代码
XML
<!--启用二级缓存-->
<setting name="cacheEnabled" value="true"/>
<!--禁用二级缓存-->
<setting name="cacheEnabled" value="false"/>
(2)第二步:对象序列化:让所有的POJO类实现序列化接口java.io.Serializable
(3)第三步:配置映射文件:在Mapper映射文件中添加<cache/>,表示此Mapper开启二级缓存,当SqlSession对象关闭时,会将SqlSession对象的一级缓存中的数据存入到二级缓存
7、insert标签、delete标签、update标签、select标签中的flushCache属性
(1)作用:设置所在标签中的SQL语句在被调用时是否刷新二级缓存
(2)属性值:true/false
8、cache标签中的flushInterval属性
(1)作用:在指定时间间隔刷新cache标签对应的二级缓存
(2)属性值:任意的正整数,以毫秒为单位的合理时间量
(3)特点:cache标签在默认情况下不设置时间间隔,二级缓存仅会在调用语句时刷新
9、一级缓存中的数据写入到二级缓存的时刻
只有当SqlSession对象被关闭时该SqlSession对象的一级缓存中的数据才会写入到二级缓存