在mybatis中缓存分为一级缓存和二级缓存:
一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。
二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。
1、mybatis一级缓存
一级缓存是默认开启的,所以第一次发起查询用户id为1的用户信息,先去找缓存中是否有1的用户,如果有的话拿去用,如果没有去数据库中查去。得到用户信息放入一级缓存中去。如果SqlSession去执行commit操作(执行插入、删除、更新)的话,清空SqlSession中的一级缓存,这样做就是为了让缓存中的数据保持最新,避免用户读到错误的数据。
具体体现如下代码:
@Test
public void testFindById(){
User user = userDao.findById(45);
System.out.println("查询第一次用户"+user);
User user2 = userDao.findById(45);
System.out.println("第二次查询用户"+user2);
System.out.println(user == user2);
}
以上我们对同一个id进行两次查询,结果如下我们两次查询实际只调用了一次sql语句去查询,这里就使用的mybatis一级缓存:
一级缓存清除:
(1)使用指定方法进行清除,测试代码如下:实际结果查询了两次
@Test
public void testFirstCache(){
User user1 = userDao.findById(57);
System.out.println(user1);
//sqlSession.close;
//再次获取SqlSession
//sqlSession = factory.openSession();
sqlSession.clearCache();//清空缓存
userDao = sqlSession.getMapper(UserDao.class);
User user2 = userDao.findById(57);
System.out.println(user2);
System.out.println(user1 == user2);
}
(2)执行插入、删除、更新操作进行缓存清除
@Test
public void testClearCache(){
User user1 = userDao.findById(57);
System.out.println(user1);
user1.setUserName("更新名称");
user1.setUserAddress("更新地址");
userDao.updateUser(user1);
User user2 = userDao.findById(57);
System.out.println(user2);
System.out.println(user1==user2);
}
如上我们在查询时进行更新操作,结果第二次查询时发现执行了两次sql证明缓存清除了
2、mybatis二级缓存
二级缓存需要我们手动开启,开启后sqlSession 去查询用户信息,查询到用户信息会将查询数据存储到二级缓存中。sqlSession2 去查询与 sqlSession1 相同的用户信息,首先会去缓存中找是否存在数据,如果存在直接从缓存中取出数据。如果 SqlSession3 去执行相同 mapper 映射下 sql,执行 commit 提交,将会清空该 mapper 映射下的二级缓存区域的数据。
具体代码实现如下:
SqlMapConfig.xml配置
<!--开启耳机缓存支持
因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为
false 代表不开启二级缓存。
-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
UserDao.xml配置
<!--根据用户id查询用户
将 UserDao.xml 映射文件中的<select>标签中设置 useCache=”true”代表当前这个 statement 要使用
二级缓存,如果不使用二级缓存可以设置为 false。
注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。
-->
<select id="findById" resultMap="userMap" parameterType="Integer" useCache="true">
select * from user where id = #{id};
</select>
调用具体方法:
@Test
public void testSecondCache(){
SqlSession sqlSession1 = factory.openSession();
UserDao dao1 = sqlSession1.getMapper(UserDao.class);
User user1 = dao1.findById(57);
System.out.println(user1);
sqlSession1.close();//一级缓存消失
SqlSession sqlSession2 = factory.openSession();
UserDao dao2 = sqlSession2.getMapper(UserDao.class);
User user2 = dao2.findById(57); //实际调用了二级缓存
System.out.println(user2);
sqlSession2.close();
System.out.println(user1 == user2);
}
结果如下: