二级缓存是mapper级别的缓存,Mybatis默认是没有开启二级缓存多个SqlSession去操作同一个Mapper的sql语句,多個SqlSession可以共用二级缓存也就是说,二级缓存是跨SqlSession的因此二级缓存的作用范围更大。
UserMapper有一个二级缓存区域(按namespace分)其它mapper也有自己的二级緩存区域(按namespace分)。每一个namespace的mapper都有一个二级缓存区域两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中
第一次调鼡mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内
第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对應的二级缓存内取结果
如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作此时会清空该namespace下的二级缓存。
sqlsession对象销毁mapper中的二级缓存数據仍然存在
2、在映射文件中,加入以下内容开启二级缓存:
由于二级缓存的数据不一定都是存储到内存中,它的存储介质多种多样所以需要给缓存的对象执行序列化。
如果该类存在父类那么父类也要实现序列化。
该statement中设置userCache=false可以禁用当前select语句的二级缓存即每次查询嘟是去数据库中查询,默认情况下是true即该statement使用二级缓存。
Spring和MyBatis整合时 每次查询之后都要进行关闭sqlSession,关闭之后数据被清空所以spring整合之后,如果没有事务一级缓存是没有意义的。而如果开启二级缓存的话关闭sqlsession后,会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中这样,缓存在sqlsession关闭之后依然存在
二级缓存是建立在同一个namespace下的,如果对表的操作查询可能有多个namespace那么得到的数据就是错误的。
订单和订单详情orderMapper、orderDetailMapper。在查询订单详情时我们需要把订单信息也查询出来那么这个订单详情的信息被二级缓存在orderDetailMapper的namespace中,这个时候有人要修改订单的基本信息那就是在orderMapper的namespace下修改,他是不会影响到orderDetailMapper的缓存的那么你再次查找订单详情时,拿到的是缓存的数据这个数据其实已经是过时的。
根据以上想要使用二级缓存时需要想好两个问题:
- 对该表的操作与查询都在同一个namespace下,其他的namespace如果有操作就会发生数据的脏读。
- 对关聯表的查询关联的所有表的操作都必须在同一个namespace。