一文彻底读懂优秀开源产品MyBatis一级缓存设计( 二 )


代码如下:
@Testpublic void testUpdate() throws IOException {try (SqlSession sqlSession = sqlSessionFactory.openSession()) {// 同一个会话 第一次查询System.out.println("第一次会会话的 第一次查询");OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);List orders = orderMapper.queryById(620898339119480832L);Order order = orders.get(0);order.setAmount(12L);// 进行更新orderMapper.updateByPrimaryKey(order);// 同一个会话 第二次查询System.out.println("第一次会会话的 第二次查询");List orders2 = orderMapper.queryById(620898339119480832L);System.out.println(JSON.toJSONString(orders2));}}日志信息如下:
一文彻底读懂优秀开源产品MyBatis一级缓存设计文章插图
分析:第一次查询打印了 sql 日志 , 然后进行数据更新 , 最后进行第二次查询发现仍旧查询数据库 , 说明缓存已经失效 。
结论:同一个会话如果有更新操作则缓存清除 。
3、导致脏数据
模拟思路:打开两个会话 , 第一个会话查询数据库获取数据后, 接着第二个会话修改数据 , 最后第一个会话再查询数据 , 那最后这次查询如果和第一次查询相同 , 那说明一级缓存会导致脏数据问题 。
代码如下:
@Testpublic void testDirtyData() throws IOException {SqlSession sqlSession1 = sqlSessionFactory.openSession(true);SqlSession sqlSession2 = sqlSessionFactory.openSession(true);try {// 同一个会话 第一次查询OrderMapper orderMapper1 = sqlSession1.getMapper(OrderMapper.class);OrderMapper orderMapper2 = sqlSession2.getMapper(OrderMapper.class);List orders = orderMapper1.queryById(620898339119480832L);System.out.println("第一次会会话第一次查询的结果" + orders);Order order1 = getOrder(orders);System.out.println("=========更新数据======");orderMapper2.updateByPrimaryKey(order1);sqlSession2.commit();List orders1 =orderMapper1.queryById(620898339119480832L);System.out.println("第二次查询:"+JSON.toJSONString(orders1));}catch (Exception e){sqlSession1.close();sqlSession2.close();}}日志信息如下:
一文彻底读懂优秀开源产品MyBatis一级缓存设计文章插图
分析:第一个会话第一次查询 amount 值是1212 , 第二会话将 amount 更改为666 , 第一个会话再次查询数据获取的 amount 值为1212 , 这说明第一个会话的第二次查询命中缓存导致了脏数据问题 。
结论:一级缓存在多会话中会导致脏数据 。
解决方式:在配置一级缓存作用范围的时候将其设置为 STATEMENT , 那么缓存仅对当前执行的语句有效 , 当语句执行完毕后 , 缓存就会被清空 。
设置方式:
【一文彻底读懂优秀开源产品MyBatis一级缓存设计】