天天看点

Java——Mybatis二级缓存一、什么是二级缓存二、二级缓存原理三、开启二级缓存 四、如何解决一级缓存中Spring和Mybatis中sqlSession关闭的问题? 四、问题

一、什么是二级缓存

二级缓存是mapper级别的缓存,Mybatis默认是没有开启二级缓存。多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,也就是说,二级缓存是跨SqlSession的,因此二级缓存的作用范围更大。

UserMapper有一个二级缓存区域(按namespace分),其它mapper也有自己的二级缓存区域(按namespace分)。每一个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。

二、二级缓存原理

Java——Mybatis二级缓存一、什么是二级缓存二、二级缓存原理三、开启二级缓存 四、如何解决一级缓存中Spring和Mybatis中sqlSession关闭的问题? 四、问题

不同的sqlsession都要调用mapper下的sql语句发起数据库请求。 

第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。

第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。

如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。

sqlsession对象销毁mapper中的二级缓存数据仍然存在。

三、开启二级缓存

1、  在核心配置文件SqlMapConfig.xml中加入以下内容(开启二级缓存总开关):

cacheEnabled设置为 true

Java——Mybatis二级缓存一、什么是二级缓存二、二级缓存原理三、开启二级缓存 四、如何解决一级缓存中Spring和Mybatis中sqlSession关闭的问题? 四、问题

2、在映射文件中,加入以下内容,开启二级缓存:

Java——Mybatis二级缓存一、什么是二级缓存二、二级缓存原理三、开启二级缓存 四、如何解决一级缓存中Spring和Mybatis中sqlSession关闭的问题? 四、问题

3、实现序列化

由于二级缓存的数据不一定都是存储到内存中,它的存储介质多种多样,所以需要给缓存的对象执行序列化。

如果该类存在父类,那么父类也要实现序列化。

Java——Mybatis二级缓存一、什么是二级缓存二、二级缓存原理三、开启二级缓存 四、如何解决一级缓存中Spring和Mybatis中sqlSession关闭的问题? 四、问题

禁用二级缓存

该statement中设置userCache=false可以禁用当前select语句的二级缓存,即每次查询都是去数据库中查询,默认情况下是true,即该statement使用二级缓存。

Java——Mybatis二级缓存一、什么是二级缓存二、二级缓存原理三、开启二级缓存 四、如何解决一级缓存中Spring和Mybatis中sqlSession关闭的问题? 四、问题

刷新二级缓存

Java——Mybatis二级缓存一、什么是二级缓存二、二级缓存原理三、开启二级缓存 四、如何解决一级缓存中Spring和Mybatis中sqlSession关闭的问题? 四、问题

四、如何解决一级缓存中Spring和Mybatis中sqlSession关闭的问题?

Spring和MyBatis整合时, 每次查询之后都要进行关闭sqlSession,关闭之后数据被清空。所以spring整合之后,如果没有事务,一级缓存是没有意义的。而如果开启二级缓存的话,关闭sqlsession后,会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中。这样,缓存在sqlsession关闭之后依然存在。

四、问题

二级缓存是建立在同一个namespace下的,如果对表的操作查询可能有多个namespace,那么得到的数据就是错误的。

举个例子:

订单和订单详情,orderMapper、orderDetailMapper。在查询订单详情时我们需要把订单信息也查询出来,那么这个订单详情的信息被二级缓存在orderDetailMapper的namespace中,这个时候有人要修改订单的基本信息,那就是在orderMapper的namespace下修改,他是不会影响到orderDetailMapper的缓存的,那么你再次查找订单详情时,拿到的是缓存的数据,这个数据其实已经是过时的。

根据以上,想要使用二级缓存时需要想好两个问题:

  • 对该表的操作与查询都在同一个namespace下,其他的namespace如果有操作,就会发生数据的脏读。
  • 对关联表的查询,关联的所有表的操作都必须在同一个namespace。

参考博客:

https://blog.csdn.net/Searchin_R/article/details/85220734

https://blog.csdn.net/hd243608836/article/details/78654984