mybaits提供一级缓存,和二级缓存区别
一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。但如果开启了二级缓存,那么在关闭sqlsession后,会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中。 对sqlsession执行commit操作,也就意味着用户执行了update、delete等操作,那么数据库中的数据势必会发生变化,如果用户请求数据仍然使用之前内存中的数据,那么将读到脏数据。所以在执行sqlsession操作后,会清除保存数据的HashMap,用户在发起查询请求时就会重新读取数据并放入一级缓存中了。 如何开启二级缓存:
代码语言:javascript复制1、 在mybatis总配置文件中加入一行设置
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
2、在需要开启二级缓存的mapper.xml中加入caceh标签
<cache/>
二级缓存是mapper级别的缓存,按namespace分,如果namespace相同则使用同一个相同的二级缓存区,多个SqlSession去操作数据库得到数据会存在二级缓存区域。注意:即使开启了二级缓存,不同的sqlsession之间的缓存数据也不是想互访就能互访的,必须等到sqlsession关闭了以后,才会把其一级缓存中的数据写入二级缓存。
但是我们并不使用mybaits提供的二级缓存,理由如下:
- 缓存是以namespace为单位的,不同namespace下的操作互不影响。例如UserMapper.xml包含一个命名空间,所有针对user表的insert,update,delete操作都在这个命名空间下。假设另外一个XXXMapper.xml对user表的内容进行select查询,并将查询结果二级缓存。然后我们对user表进行insert,update或者delete操作,insert,update,delete操作会清空所在namespace下的全部缓存,但是XXXMapper.xml命名空间下的缓存却没有变化,导致XXXMapper.xml再次查询错误。
- 多表操作不能使用缓存。比如我要
查询某一个作者的全部文章
,作者为一张表,文章为一张表。首先,对不同表的增删改一般放到不同的namespace,原因是:假设我将多表的全部操作放到一个namespace,那么我对任意一张表的增删改都会触发清空这个namespace的全部缓存,导致缓存一直在变,那我就要一直查表,那要缓存也没意义了。然后,假设将查询某一个作者的全部文章
这一操作放到作者所在的那个namespace,那么文章表的增删改由于和查询某一个作者的全部文章
这一操作不在同一namespace,导致这一操作的二级缓存不变,查询错误。 所以放弃Mybatis二级缓存,在业务层使用可控制的二级缓存代替更好,即服务器上的缓存。推荐使用redis或者ehcache做分布式二级缓存