一、一级缓存的不共享性
每个SqlSession都有独立的HashMap缓存数据
protected PerpetualCache localCache;//一级缓存
所以Mybatis的一级缓存是不共享的
二、并发下的脏读问题
我们设想有两个集群节点
我们先执行查的操作假设A执行了查询把一条数据查询出来加载到自己的缓存A中,此时B正好修改了A查询出来的数据。那么我们还是相同的数据查询的时候如果到A的话就会从缓存中读取上次查询的数据,虽然看着数据库的数据已经修改了,但是A在执行查询的时候读取出来的还是修改之前的数据。此时就出现了脏读
三、怎么解决
1.在SQL语句中随机生成不同的参数
<select id="selectAllUser" resultType="com.mybatis.entity.User">
select * from user where #{randomString} =#{randomString}
</select>
结果
==> Preparing: select * from user where ? =?
==> Parameters: -2003338679(Integer), -2003338679(Integer)
<== Columns: id, username, password
<== Row: 1, 小王, 123456
<== Row: 2, 小李, 123456
<== Total: 2
User{id=1, username='小王', password='123456'}
User{id=2, username='小李', password='123456'}
------------------------第二次调用-------------------------------
==> Preparing: select * from user where ? =?
==> Parameters: 824140049(Integer), 824140049(Integer)
<== Columns: id, username, password
<== Row: 1, 小王, 123456
<== Row: 2, 小李, 123456
<== Total: 2
User{id=1, username='小王', password='123456'}
User{id=2, username='小李', password='123456'}
这样可以解决集群下脏读问题但是有个弊端我们的缓存中会存在好多数据,Map集合会爆的
2.开启二级缓存
也就是配置我们redis或者别的中间件去缓存我们的数据, 这样的话一级缓存就没用了。就会走二级缓存去查询了具体 配置可以看Springboot整合Redis
3.强制清除一级缓存
sqlSession中提供了一个clearCache方法可以去清除一级缓存,当我们查完之后清除一下就可以了
sqlSession.clearCache();//强制清楚缓存
4.创建新的sqlSession连接
创建新的sqlSession连接就会创建一个新的一级缓存集合,这样的话就会去数据库查询,不走之前的一级缓存,这样也可以解决我们的脏读问题