🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ***** 使用缓存可以使应用更快地获取数据, 避免频繁的数据库交互,尤其是在查询越多、 缓存命中率越高的情况下, 使用缓存的作用就越明显。 # 7.1 一级缓存 mybatis默认启动一级缓存(本地缓存) ,一级缓存可以产生一些难以发现的错误。 **1 在CacheTest.java文件中** ``` public class CacheTest extends BaseMapperTest { @Test public void testL1Cache(){ //获取 sqlSession SqlSession sqlSession = getSqlSession(); SysUser user1 = null; try { //获取 UserMapper 接口 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //调用 selectById 方法,查询 id = 1 的用户 user1 = userMapper.selectById(1l); //对当前获取的对象重新赋值 user1.setUserName("New Name"); //再次查询获取 id 相同的用户 SysUser user2 = userMapper.selectById(1l); //没有更新数据库,但是user2的用户名和我们 user1的用户名字相同 Assert.assertEquals("New Name", user2.getUserName()); //user2 和 user1 完全就是同一个实例 Assert.assertEquals(user1, user2); } finally { //关闭当前的 sqlSession sqlSession.close(); } System.out.println("开启新的 sqlSession"); //开始另一个新的 session sqlSession = getSqlSession(); try { //获取 UserMapper 接口 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //调用 selectById 方法,查询 id = 1 的用户 SysUser user2 = userMapper.selectById(1l); //user2的用户名和我们 user1的用户名字不相同,user2用户名还是admin(表中的数据值) Assert.assertNotEquals("New Name", user2.getUserName()); //这里的user2 和 user1不是同一个实例 Assert.assertNotEquals(user1, user2); //执行删除操作 userMapper.deleteById(2L); //获取 user3 SysUser user3 = userMapper.selectById(1l); //这里的 user2 和 user3 是两个不同的实例 Assert.assertNotEquals(user2, user3); } finally { //关闭 sqlSession sqlSession.close(); } } } ``` **第一个try块** MyBatis的一级缓存存在于 SqlSession的生命周期中, 在同一个SqlSession中查询(SELECT)时, MyBatis会把执行的方法和参数通过算法生成缓存的键值, 将键值和查询结果存入一个Map对象中。 如果同一个 SqlSession中执行的方法和参数完全一致, 那么通过算法会生成相同的键值。 当使用相同参数执行同一个方法时, 根据Map缓存对象中已经存在的键值返回缓存中的对象。所以第一个try块中的user1和user2是同一个实例,修改user1会影响user2。 **第二个try块** 在关闭第一个 SqlSession 后, 又重新获取了一个 SqlSession, 因此 又重新查询了user2, 这时在日志中输出了数据库查询SQL, user2是一 个新的实例, 和user1没有任何关系。 这是因为**一级缓存是和SqlSession 绑定的, 只存在于SqlSession的生命周期中。** 接下来执行了一个deleteById操作, 然后使用相同的查询方法和参数获 取了user3实例, 从日志和结果来看, user3 和 user2 也是完全不同的两 个对象。 这是因为**任何的 INSERT、 UPDATE、 DELETE操作都会清空一级缓存**, 所以查询user3的时候由于缓存不存在, 就会再次执行数据库查询获取数据。 **不让selectById方法使用一级缓存** ![](https://box.kancloud.cn/9255576ce3648df837c07f75e427d5ad_628x84.png) 这个属性配置为true后, 会在查询数据前清空当前的一级缓存, 因此该方法每次都会重新从数据库中查询数据。但是由于这个方法清空了一级缓存, 会影响当前SqlSession中所有缓存的查询, 因此在需要反复查询获取只读数据的情况下, 会增加数据库的查询次数, 所以要避免这么使用。