二级缓存问题
情形一:
@Test public void testLv2Cache(){ SqlSession sqlSession=null; try { sqlSession = MyBatisUtils.openSession(); Goods goods = sqlSession.selectOne("goods.selectById", 2648); Goods goods2 = new Goods(); goods2.setTitle("测试标题aaaaa"); goods2.setSubTitle("测试副标题bbbbb"); goods2.setOriginalCost(200f); goods2.setCurrentPrice(400f); goods2.setDiscount(0.5f); goods2.setIsFreeDelivery(1); goods2.setCategoryId(43); sqlSession.insert("goods.insertGoods",goods2); Goods goods1 = sqlSession.selectOne("goods.selectById", 2648); System.out.println(goods.hashCode()+":"+ goods); System.out.println(goods1.hashCode()+":"+goods1); } catch (Exception e) { throw new RuntimeException(e); } finally { MyBatisUtils.closeSession(sqlSession); } System.out.println("-----------------------------------"); try { sqlSession = MyBatisUtils.openSession(); Goods goods = sqlSession.selectOne("goods.selectById", 2648); Goods goods1 = sqlSession.selectOne("goods.selectById", 2648); System.out.println(goods.hashCode()+":"+ goods); System.out.println(goods1.hashCode()+":"+goods1); } catch (Exception e) { throw new RuntimeException(e); } finally { MyBatisUtils.closeSession(sqlSession); } System.out.println("-----------------------------------"); try { sqlSession = MyBatisUtils.openSession(); Goods goods = sqlSession.selectOne("goods.selectById", 2648); Goods goods1 = sqlSession.selectOne("goods.selectById", 2648); System.out.println(goods.hashCode()+":"+ goods); System.out.println(goods1.hashCode()+":"+goods1); } catch (Exception e) { throw new RuntimeException(e); } finally { MyBatisUtils.closeSession(sqlSession); } }
情形一的测试结果:
LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.0 JdbcTransaction:143 =>[DEBUG] Opening JDBC Connection JdbcTransaction:107 =>[DEBUG] Setting autocommit to false on JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] BaseJdbcLogger:135 =>[DEBUG] ==> Preparing: select * from t_goods where goods_id = ? BaseJdbcLogger:135 =>[DEBUG] ==> Parameters: 2648(Integer) BaseJdbcLogger:135 =>[DEBUG] <== Total: 1 BaseJdbcLogger:135 =>[DEBUG] ==> Preparing: insert into t_goods(title,sub_title,original_cost,current_price,discount,is_free_delivery,category_id) values(?,?,?,?,?,?,?) BaseJdbcLogger:135 =>[DEBUG] ==> Parameters: 测试标题aaaaa(String), 测试副标题bbbbb(String), 200.0(Float), 400.0(Float), 0.5(Float), 1(Integer), 43(Integer) BaseJdbcLogger:135 =>[DEBUG] <== Updates: 1 BaseJdbcLogger:135 =>[DEBUG] ==> Preparing: select last_insert_id() BaseJdbcLogger:135 =>[DEBUG] ==> Parameters: BaseJdbcLogger:135 =>[DEBUG] <== Total: 1 LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.0 BaseJdbcLogger:135 =>[DEBUG] ==> Preparing: select * from t_goods where goods_id = ? BaseJdbcLogger:135 =>[DEBUG] ==> Parameters: 2648(Integer) BaseJdbcLogger:135 =>[DEBUG] <== Total: 1 680988889:新安怡新生宝宝沐浴露200毫升 SCF981/02 1511574902:新安怡新生宝宝沐浴露200毫升 SCF981/02 JdbcTransaction:86 =>[DEBUG] Rolling back JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] JdbcTransaction:130 =>[DEBUG] Resetting autocommit to true on JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] JdbcTransaction:97 =>[DEBUG] Closing JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] ----------------------------------- LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.0 JdbcTransaction:143 =>[DEBUG] Opening JDBC Connection JdbcTransaction:107 =>[DEBUG] Setting autocommit to false on JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] BaseJdbcLogger:135 =>[DEBUG] ==> Preparing: select * from t_goods where goods_id = ? BaseJdbcLogger:135 =>[DEBUG] ==> Parameters: 2648(Integer) BaseJdbcLogger:135 =>[DEBUG] <== Total: 1 LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.0 1077873186:新安怡新生宝宝沐浴露200毫升 SCF981/02 1077873186:新安怡新生宝宝沐浴露200毫升 SCF981/02 JdbcTransaction:130 =>[DEBUG] Resetting autocommit to true on JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] JdbcTransaction:97 =>[DEBUG] Closing JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] ----------------------------------- LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.2 LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.3333333333333333 1077873186:新安怡新生宝宝沐浴露200毫升 SCF981/02 1077873186:新安怡新生宝宝沐浴露200毫升 SCF981/02
情形二:
@Test public void testLv2Cache(){ SqlSession sqlSession=null; try { sqlSession = MyBatisUtils.openSession(); Goods goods = sqlSession.selectOne("goods.selectById", 2648); Goods goods1 = sqlSession.selectOne("goods.selectById", 2648); System.out.println(goods.hashCode()+":"+ goods.getTitle()); System.out.println(goods1.hashCode()+":"+goods1.getTitle()); } catch (Exception e) { throw new RuntimeException(e); } finally { MyBatisUtils.closeSession(sqlSession); } System.out.println("-----------------------------------"); try { sqlSession = MyBatisUtils.openSession(); Goods goods = sqlSession.selectOne("goods.selectById", 2648); Goods goods2 = new Goods(); goods2.setTitle("测试标题aaaaa"); goods2.setSubTitle("测试副标题bbbbb"); goods2.setOriginalCost(200f); goods2.setCurrentPrice(400f); goods2.setDiscount(0.5f); goods2.setIsFreeDelivery(1); goods2.setCategoryId(43); sqlSession.insert("goods.insertGoods",goods2); Goods goods1 = sqlSession.selectOne("goods.selectById", 2648); System.out.println(goods.hashCode()+":"+ goods.getTitle()); System.out.println(goods1.hashCode()+":"+goods1.getTitle()); } catch (Exception e) { throw new RuntimeException(e); } finally { MyBatisUtils.closeSession(sqlSession); } System.out.println("-----------------------------------"); try { sqlSession = MyBatisUtils.openSession(); Goods goods = sqlSession.selectOne("goods.selectById", 2648); Goods goods1 = sqlSession.selectOne("goods.selectById", 2648); System.out.println(goods.hashCode()+":"+ goods.getTitle()); System.out.println(goods1.hashCode()+":"+goods1.getTitle()); } catch (Exception e) { throw new RuntimeException(e); } finally { MyBatisUtils.closeSession(sqlSession); } }
情形二的测试结果:
DruidDataSource:1002 =>[INFO] {dataSource-1} inited LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.0 JdbcTransaction:143 =>[DEBUG] Opening JDBC Connection JdbcTransaction:107 =>[DEBUG] Setting autocommit to false on JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] BaseJdbcLogger:135 =>[DEBUG] ==> Preparing: select * from t_goods where goods_id = ? BaseJdbcLogger:135 =>[DEBUG] ==> Parameters: 2648(Integer) BaseJdbcLogger:135 =>[DEBUG] <== Total: 1 LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.0 1783966110:新安怡新生宝宝沐浴露200毫升 SCF981/02 1783966110:新安怡新生宝宝沐浴露200毫升 SCF981/02 JdbcTransaction:130 =>[DEBUG] Resetting autocommit to true on JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] JdbcTransaction:97 =>[DEBUG] Closing JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] ----------------------------------- LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.3333333333333333 JdbcTransaction:143 =>[DEBUG] Opening JDBC Connection JdbcTransaction:107 =>[DEBUG] Setting autocommit to false on JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] BaseJdbcLogger:135 =>[DEBUG] ==> Preparing: insert into t_goods(title,sub_title,original_cost,current_price,discount,is_free_delivery,category_id) values(?,?,?,?,?,?,?) BaseJdbcLogger:135 =>[DEBUG] ==> Parameters: 测试标题aaaaa(String), 测试副标题bbbbb(String), 200.0(Float), 400.0(Float), 0.5(Float), 1(Integer), 43(Integer) BaseJdbcLogger:135 =>[DEBUG] <== Updates: 1 BaseJdbcLogger:135 =>[DEBUG] ==> Preparing: select last_insert_id() BaseJdbcLogger:135 =>[DEBUG] ==> Parameters: BaseJdbcLogger:135 =>[DEBUG] <== Total: 1 LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.5 BaseJdbcLogger:135 =>[DEBUG] ==> Preparing: select * from t_goods where goods_id = ? BaseJdbcLogger:135 =>[DEBUG] ==> Parameters: 2648(Integer) BaseJdbcLogger:135 =>[DEBUG] <== Total: 1 1783966110:新安怡新生宝宝沐浴露200毫升 SCF981/02 1511574902:新安怡新生宝宝沐浴露200毫升 SCF981/02 JdbcTransaction:86 =>[DEBUG] Rolling back JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] JdbcTransaction:130 =>[DEBUG] Resetting autocommit to true on JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] JdbcTransaction:97 =>[DEBUG] Closing JDBC Connection [com.alibaba.druid.pool.DruidStatementConnection@40db2a24] ----------------------------------- LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.6 LoggingCache:60 =>[DEBUG] Cache Hit Ratio [goods]: 0.6666666666666666 1783966110:新安怡新生宝宝沐浴露200毫升 SCF981/02 1783966110:新安怡新生宝宝沐浴露200毫升 SCF981/02
说明:默认开启了一级缓存,手动开启了二级缓存
相同点:情形1和情形2中都含有三段相同代码
不同点:
情形1在第一段代码查询中间插入了insert()不提交
情形2在第二段代码查询中间插入了insert()不提交
问题:
情形1哈希码 —— a b c c c c
680988889 (a)
1511574902 (b)
-------------
1077873186 (c)
1077873186 (c)
-------------
1077873186 (c)
1077873186 (c)
情形2哈希码 —— a a a b a a
1783966110 (a)
1783966110 (a)
--------------
1783966110 (a)
1511574902 (b)
--------------
1783966110 (a)
1783966110 (a)
情形1和情形2无法自圆其说,因为都开启了一级缓存和二级缓存,请解释?谢谢
正在回答
同学你好,1、在MyBatis中,开启了二级缓存并且在代码中插入了一个不提交的insert操作时,这确实会对一级缓存和二级缓存产生干扰,尤其是当这些操作在同一个SqlSession中执行时。
2、下面是对这种情形的详细分析:
1)一级缓存(SqlSession级别):
当执行第一次查询时,MyBatis会查询数据库并将结果放入一级缓存。
接下来,执行了一个insert操作来插入一个新的商品记录(goods2)。由于这个insert操作没有提交(即没有调用sqlSession.commit()),这个变更在数据库中是看不到的,但它会清空一级缓存,因为MyBatis认为数据可能已经发生了改变。
由于一级缓存已被清空,当您再次执行相同的查询时,MyBatis不会从一级缓存中获取结果,而是会再次查询数据库。
2)二级缓存(Mapper级别):
当执行第一次查询时,MyBatis会首先检查二级缓存中是否有结果。如果二级缓存中没有结果,它会查询数据库,并将结果同时放入一级缓存和二级缓存。
接着,当执行insert操作时,由于这个操作没有提交,它不会影响数据库中的实际数据,但MyBatis会认为数据已经改变,并清空所有相关的一级缓存和二级缓存。这意味着,如果其他SqlSession尝试从二级缓存中获取相同ID的商品,它们将不会看到insert操作的结果,因为缓存已经被清空。
由于insert操作没有提交,一级缓存和二级缓存都会被清空。这意味再进行查询,MyBatis将不得不重新查询数据库,而不是从缓存中获取结果。
3、在不同的代码中书写增删改操作,都可能会对一级缓存和二级缓存产生干扰,所以出现的结果是不同的。
祝学习愉快!
- 参与学习 2024 人
- 提交作业 1318 份
- 解答问题 1228 个
2024重磅革新,超百小时内容豪华升级,加速提升高级技能与高薪就业竞争力 课程紧贴企业最新人才需求,历经7年持续迭代,帮助万名学子入行转行 从零起点到高阶实战,学习路径稳健顺滑,成就从小白到工程师高薪
了解课程
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星