为了提升查询效率,提高用户体验,MyBatis提供了数据缓存支持,依据数据缓存的有效范围默认定义了一级缓存和二级缓存
一级缓存:
- 该级缓存默认开启,不能关闭;
- 该级缓存为SqlSession级别的缓存,也称为本地缓存;
- 以下4种情况将会导致该级缓存失效:
a、在不同SqlSession中查询数据,因为一级缓存是在一个sqlSession中生效的,所以那,如果在不同的sqlSession中肯定是不行的。
具体演示如下:
package com.jd.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.jd.userInfo.dao.IUserInfoDao;
import com.jd.vo.UserInfo;
public class Test {
public static void main(String[] args) {
try {
InputStream inputStream =Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession =sqlSessionFactory.openSession();
IUserInfoDao userInfoDao = sqlSession.getMapper(IUserInfoDao.class);
List<UserInfo> list =userInfoDao.getUser();
System.out.println(list.size());
sqlSession.close();
sqlSession = sqlSessionFactory.openSession();
userInfoDao = sqlSession.getMapper(IUserInfoDao.class);
list = userInfoDao.getUser();
System.out.println(list.size());
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果如下:
b、相同SqlSession中查询数据,但查询条件不同,也会使其失效。
public class Test {
public static void main(String[] args) {
try {
InputStream inputStream =Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession =sqlSessionFactory.openSession();
IUserInfoDao userInfoDao = sqlSession.getMapper(IUserInfoDao.class);
List<UserInfo>list = userInfoDao.select("%7%");
System.out.println("数据库查询条数:"+list.size());
list = userInfoDao.select("%8%");
System.out.println("数据库查询条数:"+list.size());
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果分析:当我们执行第一个查询时,我们在缓存中是一条数据,如果缓存不失效的话,那么我们第二次查询就不会有数据。但是我第二次查询有数据,所以是失效的。
c、相同SqlSession中查询数据,但两次查询之间执行了增删改操作
public class Test {
public static void main(String[] args) {
try {
InputStream inputStream =Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession =sqlSessionFactory.openSession();
IUserInfoDao userInfoDao = sqlSession.getMapper(IUserInfoDao.class);
List<UserInfo>list = userInfoDao.select("%7%");
System.out.println("数据库查询name中带7的条数:"+list.size());
boolean frag=userInfoDao.delete("888");
System.out.println("删除结果:"+frag);
sqlSession.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果&结果分析:数据库查询name中带7的条数是1,如果缓存不失效的话,那么我们不会删除掉name为888的数据(因为缓存中没有),但是我们依旧删除了name为888的数据,说明此时的一级缓存已经失效。
d、相同SqlSession中查询数据,但第二次查询前,程序调用SqlSession对象clearCache()方法手动清除了一级缓存:
这个就不用实验了,因为...手动清除,肯定没有了呀。
-
二级缓存:
- 1、该级缓存默认不开启,但如果使用二级缓存需要在每个XML映射文件中添加<cache></cache>以配置该级缓存。二级缓存可以通过在全局配置文件配置setting标签来关闭该级缓存
- 2、该级缓存为namespace级别的缓存
- 3、工作机制:通过SqlSession查询数据,这些数据将会放到当前会话的一级缓存中;如果当前会话关闭,则一级缓存中的数据会被保存到二级缓存中,此后新的SqlSession将从二级缓存中查找数据;
-
4、select标签的useCache属性用于设置是否使用二级缓存;insert、update、delete或select标签均有flushCache属性,其中增删改默认true,即sql执行以后,会同时清空一级和二级缓存,查询默认false。
-
实验:
-
public class Test { public static void main(String[] args) { try { InputStream inputStream =Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession =sqlSessionFactory.openSession(); IUserInfoDao userInfoDao = sqlSession.getMapper(IUserInfoDao.class); List<UserInfo>list = userInfoDao.select("%7%"); System.out.println("数据库查询name中带7的条数:"+list.size()); sqlSession.close(); sqlSession = sqlSessionFactory.openSession(); userInfoDao = sqlSession.getMapper(IUserInfoDao.class); boolean frag=userInfoDao.delete("777"); System.out.println("删除缓存中name为777的结果:"+frag); list = userInfoDao.select("%7%"); System.out.println("缓存中查询name中带7的条数:"+list.size()); sqlSession.close(); } catch (IOException e) { e.printStackTrace(); } } }
- 结果如下:
- 分析:由3得(通过SqlSession查询数据库查询name中带7的条数,这些数据将会放到当前会话的一级缓存中;当前会话关闭,则一级缓存中的数据会被保存到二级缓存中,此后新的SqlSession将从二级缓存中处理数据),所以我们删除的是二级缓存中的 数据。不是数据库中的数据。
注意:增删改flushCache默认true。如果我们改为false,此时就会清空一级缓存和二级缓存。
执行结果如下: