MyBatis:缓存机制详解
Mybatis查询缓存分为一级缓存和二级缓存,一级缓存属于sqlsession
级别,二级缓存属于Mapper
级别。
Mybatis通过缓存机制可减轻直接访问数据库的压力,提高数据库性能。
Mybatis默认开启一级缓存,但与Spring
整合后会缓存失效。
- 一级缓存是
SqlSession
级别的缓存,PerpetualCache
。 - 二级缓存是
mapper
级别的缓存。是多个SqlSession
共享的。
一级缓存:sqlSession级别
一级缓存是SqlSession级别的缓存,在操作数据库时需要构造SqlSession对象,在对象中有一个HashMap
用于存储缓存数据。不同的SqlSession之间的缓存数据区域HashMap是互不影响的。
Mybatis缓存机是基于id
进行缓存的,也就是说,Mybatis使用HashMap缓存数据时,是使用对象的id作为key
,而对象作为value
保存的。
第一次以id为1进行查询执行了一条select语句,第二次获取id为1的数据,不会再执行 select
语句。如果不执行session.commit()
,操作没有提交到数据库,此时Mybatis不会清空SqlSession缓存。
若在第一次查询id为的数据时执行了一条select语句,接下来执行了一个update,delete,insert into
操作,Mybatis为了保证缓存中存储的最新信息,会清空SqlSession缓存。
因一级缓存是SqlSession级别的,如果在执行第一次根据id查询后,执行了close()
方法,该方法会关闭SqlSession缓存,第二次根据相同的id查询,一级缓存也就是SqlSession缓存是一个新的对象,会再次执行select语句。
在实际的项目开发中,往往会将Mybatis
与Spring
整合,SqlSession会交给Spring管理,每查询结束后,Spring会清空当前的SqlSession释放资源,也就每次查询所使用的SqlSession是不相同的,导致Mybatis的一级缓存失效。
二级缓存:mapper级别
二级缓存是mapper
级别的缓存,是多个SqlSession使用同一个mapper的sql语句去操作数据库,得到的数据会存在二级缓存区域。
二级缓存也是使用HashMap
进行数据存储的,范围比一级缓存更大,是跨SqlSession的,多个SqlSession可以共用二级缓存。
二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace
。不同的SqlSession两次执行相同namespace下的sql语句,且向sql中传递的参数也相同,即最终执行相同的sql语句,即第一次执行完毕会将从数据库查询到的数据写入缓存(内存),第二次查询会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。
当Mybatis在一级缓存中没有找到与id对应的对象时,就会去二级缓存中查找,如果还没有,就去数据库查找。
Mybatis默认没有开启二级缓存,需要在setting
全局参数中配置开启二级缓存。开启配置如下:
在Mybatis的配置文件mybatis-config.xml
配置
1 | <settings> |
开始当前mapper的namespace下的二级缓存,在Mapper.xml
文件增加配置:
1 | <!-- 例:xxxMapper.xml,创建一个LRU缓存,并每隔60秒刷新,最大储储512个对象,返回对象是只读 --> |
cache开启当前mapper的namespace下的二级缓存。该元素属性设置如下:
flushInterval
刷新间隔,单位毫秒,默认不设置没有刷新间隔,在调用时刷新。size
缓存数目,需要缓存的对象数目,默认值是1024。readOnly
只读,可设置为true或false。默认false,可读写,返回的是缓存对象的拷贝(通过序列化),会慢些,但安全。
eviction的策略:
LRU
:最近最少使用的策略,移除最长时间不被使用的对象。FIFO
:先进先出策略,按对象进入缓存的存序来移除它他。SOFT
:软引用策略,移除基于垃圾回收器状态和软引用规则的对象。WEAK
:弱引用策略,更积极地移除基于垃圾收集器状态和弱引用规则的对象。
使用二级缓存时,与查询结果映射的Java对象,必须实现序列化接口:java.io.Serializable。如果存在父类,其父类成员都需要实现序列化接口。
实现序列化接口是为了对缓存数据进行序列化和反序列化操作,因为二级缓存数据存储介质多样,不一定在内存,有可能是硬盘或远程服务器。
在select中设置useCache=false
,可以禁用当前select语句的二级缓存,即每次查询都会发出sql查询,默认是true即开启二级缓存,则该sql会使用二级缓存。禁用缓存设置通常用于每次查询都需要最新的数据情况。
当一级缓存中没有数据时,若开启了二级缓存,则会到二级缓存中查找。