摘要:简述mybatis的一级缓存。
1、一级缓存
一级缓存也成为sqlSession级缓存,在同一个sqlSesssion内,同样的select语句只会发一条,delete,upadate,insert操作,会清楚缓存,默认开启。示例如下
示例1:在同一个sqlSession生命周期中,同样的select语句只发一次,且两次的对象是同一个。
System.out.println("一级缓存测试开始");
SqlSession sqlSession = sqlSessionFactory.openSession();
AreaDictMapper areaDictMapper = sqlSession.getMapper(AreaDictMapper.class);
AreaDict areaDict1 = areaDictMapper.selectById(1l);
AreaDict areaDict2 = areaDictMapper.selectById(1l);
Assert.assertEquals(areaDict1, areaDict2);
sqlSession.commit();
sqlSession.close();
System.out.println("一级缓存测试结束");
结果:
结论:在sqlSession的生命周期中,areaDict2和areaDict1的sql语句一样,所以areaDict2会在缓存中获取,不会重新发sql语句,且areaDict1和areaDict2是同一个对象(指向同一块内存)。
示例2:不同的sqlSession
测试代码:
System.out.println("一级缓存测试开始");
SqlSession sqlSession = sqlSessionFactory.openSession();
AreaDictMapper areaDictMapper = sqlSession.getMapper(AreaDictMapper.class);
AreaDict areaDict1 = areaDictMapper.selectById(1l);
sqlSession.commit();
sqlSession.close();
System.out.println("开启另外一个sqlSession");
SqlSession sqlSession1 = sqlSessionFactory.openSession();
AreaDictMapper areaDictMapper1 = sqlSession1.getMapper(AreaDictMapper.class);
AreaDict areaDict2 = areaDictMapper1.selectById(1l);
Assert.assertEquals(areaDict1, areaDict2);
sqlSession1.commit();
sqlSession1.close();
System.out.println("一级缓存测试结束");
结果:
结论:在sqlSession结束以后,重新开启sqlSession1,即便两者的sql语句一致,也会重新发送sql语句,而且areaDict1和2也不同。
示例3:DML操作会刷新缓存,这边以update为例
测试代码:
System.out.println("一级缓存测试开始");
SqlSession sqlSession = sqlSessionFactory.openSession();
AreaDictMapper areaDictMapper = sqlSession.getMapper(AreaDictMapper.class);
AreaDict areaDict1 = areaDictMapper.selectById(1l);
// 更新数据
areaDictMapper.updateAreaNameById("改则县", 3634);
AreaDict areaDict2 = areaDictMapper.selectById(1l);
sqlSession.commit();
sqlSession.close();
System.out.println("一级缓存测试结束");
测试结果:
结论:虽然areaDict1和areaDict2的查询sql是一样的,但是在获取areaDict2之前更新了一个数据表,所以这个时候仍然会发送两条sql,一级缓冲被清空了;两个对象也是不同的。
示例4:flushCache="true"也可以清空一级缓存
测试代码:
<select id="selectById" resultMap="BaseResultMap" flushCache="true">
select
<include refid="base_column_list"/>
from area_dict
where area_dict_id = #{id}
</select>
System.out.println("一级缓存测试开始");
SqlSession sqlSession = sqlSessionFactory.openSession();
AreaDictMapper areaDictMapper = sqlSession.getMapper(AreaDictMapper.class);
AreaDict areaDict1 = areaDictMapper.selectById(1l);
AreaDict areaDict2 = areaDictMapper.selectById(1l);
Assert.assertEquals(areaDict1, areaDict2);
sqlSession.commit();
sqlSession.close();
System.out.println("一级缓存测试结束");
结果:
结论:在查询的时候清空一级缓存,每次都会重新发sql。
关于spring整合mybatis以后,在同一个事务中一级缓存生效,如果不在同一个事务中,每次操作都会新建一个sqlSession,一级缓存无法使用。详细参看大牛贴:https://www.cnblogs.com/ljdblog/p/7123430.html