MyBatis缓存机制
缓存机制是为了减轻数据库压力,提高数据库性能。
Mybatis查询缓存分为一级缓存和二级缓存,默认开启一级缓存。
- 一级缓存是
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全局参数中配置开启二级缓存。开启配置如下:
<settings> <!-- 开启二级缓存 --> <setting name="cacheEnabled" value="true"/> </settings>
开始当前mapper的namespace下的二级缓存,xxxMapper.xml
<!-- 创建一个LRU缓存,并每隔60秒刷新,最大储储512个对象,返回对象是只读 --> <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
cache开启当前mapper的namespace下的二级缓存。该元素属性设置如下:
flushInterval刷新间隔,单位毫秒,默认不设置没有刷新间隔,在调用时刷新。size缓存数目,需要缓存的对象数目,默认值是1024。readOnly只读,可设置为true或false。默认false,可读写,返回的是缓存对象的拷贝(通过序列化),会慢些,但安全。
使用二级缓存时,与查询结果映射的Java对象,必须实现java.io.Serializable接口的序列化和反序列化操作。如果存在你的父类,其成员都需要实现序列化接口。
实现序列化接口是为了对缓存数据进行序列化和反序列化操作,因为二级缓存数据存储介质多样,不一定在内存,有可能是硬盘或远程服务器。
在select中设置useCache=false,可以禁用当前select语句的二级缓存,即每次查询都会发出sql查询,默认是true即开该了二级缓存则该sql使用二级缓存。该设置通常用于每次查询都需要最新的数据情况。

浙公网安备 33010602011771号