Mybatis二级缓存实现及原理

一 Mybatis二级缓存是啥?
Mybatis的二级缓存Mapper级别的,sqlSession共享,它是把namespace做作为缓存key实现的,各个namespace是独立的,互相不影响(也就是说你执行一个查询sql方法,它会找到根据Mapper接口对应的namespace找到它的缓存Key)。而具体的sql查询语句是根据命名namespace、查询语句及查询参数等拼接的一个缓存key,value值是第一次从数据库查询出来的结果,value需要实现Serilizable接口(流化、字节化),因为mybatis的缓存value值是字节数组。
二 实现: SpringBoot默认是开启二级缓存的。如果想要单独那个Mapper实现cache,可以在xxxMapper.xml文件中添加即可。注意在xml文件中配了
三 优缺点
优点:二级缓存弥补一级缓存的不足。
一级缓存为啥不足呢?Mybatis一级缓存是sqlSession级别的,各个sqlSession的缓存数据是独立的(不共享)。由于Mybatis一般跟SpringMvc整合,在不开事务的情况下,每次请求都会开启一个sqlSession,请求完之后就关于了,缓存也清空了。所以这个缓存数据根本不能复用。
假如你在Service执行俩条查询逻辑
第一条 :userMapper.getUserByNameAndPassWord(userName, passWord); // 从数据库中查询
第二条:userMapper.getUserByNameAndPassWord(userName, passWord); // 从数据库中查询
但是开启事务就不一样了,它用的就是同一个SqlSession(为啥能用一个SqlSession,基于代理和ThreadLocal)。
缺点:对于单表查询完全没问题,但是业务开始一般都是涉及多表查询,非常容易造成暂读。
假设一个用户表t_user,用户地址表t_user_address。俩个表通过用户编码关联user_id
mapper里的定义一个查询语句查询带有用户地址信息的用户
select tu.* from t_user tu inner join t_user_address tua on tu.user_id=tua.user_id;
这样定义完全没问题,当执行之后,Mybatis会把带有地址信息的用户信息缓存起来。下次再有查询的时候,直接从缓存中获取。但是假如通过业务操作将t_user_address表中的地址信息删除了一些,Mybatis查询带地址信息的本应该从缓存中取的,但由于它是不知道t_user_address表的数据已经做了修改操作了,它还是从缓存中读数据,这时候查出来了数据比数据库多了,造成脏读。

四 弥补二级缓存缺陷
采用,作用让当前的Mapper使用其他namespace的,达到缓存数据共享。这样当用户地址表删除地址信息时,用户表的缓存信息就被情况了。

你可能感兴趣的:(面试)