mybatis的一级缓存和二级缓存
mybatis一级缓存
mybatis一级缓存是默认开启的,它在一个sqlSession会话里面的所有查询操作都会保存到缓存中,一般来说一个请求中的所有增删改查操作都是在同一个sqlSession里面的,所以我们可以认为每个请求都有自己的一级缓存,如果同一个sqlSession会话中2 个查询中间有一个 insert 、update或delete 语句,那么之前查询的所有缓存都会清空。
为了方便看结果,可以在mybatis配置文件中开启日志功能。
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
- 在开启sqlsession的时候进行两次相同的查询。
public void testCache() throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("classpath:applicationcontext.xml");
// 加载mybatis配置文件
SqlSessionTemplate sqlSessionTemplate = context.getBean
("sqlSessionTemplate", SqlSessionTemplate.class);
SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(true);
CommodityMapper mapper = sqlSession.getMapper(CommodityMapper.class);
// 查询第一次
ArrayList<Commodity> comm1 = mapper.getCommodityByUid(30);
ArrayList<Commodity> comm2 = mapper.getCommodityByUid(30);
System.out.println("两个user对象是否相等:"+(comm1 == comm2));
//释放会话
sqlSession.clearCache();
sqlSession.close();
}
通过可以看到此时只执行了一次sql操作,且两次查询的结果相等,说明第一次sql查询得到的数据被缓存到了Session中。
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@551a20d6] will not be managed by Spring
==> Preparing: select * from commodity where cid in (select cid from warehouse where uid=?);
==> Parameters: 30(Integer)
<== Total: 0
两个user对象是否相等:true
- 在两次查询操作之间加入一条插入操作,通过日志可以看到,同样的查询操作执行了两次且得到的结果不同,说明第一次查询缓存的数据在进行insert操作之后被清空了。
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@551a20d6] will not be managed by Spring
==> Preparing: select * from commodity where cid in (select cid from warehouse where uid=?);
==> Parameters: 30(Integer)
<== Total: 0
==> Preparing: insert into commodity values (?,?,?,?,?,?,?)
==> Parameters: 0(Integer), null, 0.0(Float), null, null, 0(Integer), 0.0(Float)
<== Updates: 1
==> Preparing: select * from commodity where cid in (select cid from warehouse where uid=?);
==> Parameters: 30(Integer)
<== Total: 0
两个user对象是否相等:false
mybatis二级缓存
二级缓存是全局的,也就是说;多个请求可以共用一个缓存,二级缓存需要手动开启,二级缓存的查找规则。
- 缓存会先放在一级缓存中,当sqlSession会话提交或者关闭时才会将一级缓存刷新到二级缓存中;
- 开启二级缓存后,用户查询时,会先去二级缓存中找,找不到在去一级缓存中找;
二级缓存配置:
- 单个mapper配置:前往对应mapper的配置文件添加cache标签。
<cache/>
- 所有mapper配置,mybatis配置文件配置。
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
在开启二级缓存后开启两个会话来进行同样的查询。
public void testCache() throws IOException {
// 加载mybatis配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("classpath:applicationcontext.xml");
SqlSessionTemplate sqlSessionTemplate = context.getBean
("sqlSessionTemplate", SqlSessionTemplate.class);
//第一次会话查询
SqlSession sqlSession1 = sqlSessionTemplate.getSqlSessionFactory().openSession(true);
CommodityMapper mapper = sqlSession1.getMapper(CommodityMapper.class);
mapper.getCommodityByUid(31);
sqlSession1.clearCache();
sqlSession1.close();
//第二次会话查询
SqlSession sqlSession2 = sqlSessionTemplate.getSqlSessionFactory().openSession(true);
mapper = sqlSession2.getMapper(CommodityMapper.class);
mapper.getCommodityByUid(31);
sqlSession2.clearCache();
sqlSession2.close();
}
只执行了一次查询操作,说明第一次会话查询到的数据缓存到了二级缓存中。
测试CRUD接口
删除用户
查询所有用户
添加用户
更新用户信息