MyBatis自带的缓存(其实就是Map)流程:
1、首先看二级缓存中是否有要查询的对象,如果没有就查看一级缓存中是否有要查询的对象,再没有就从数据库中查找。
2、查到后就将数据放到一级缓存中。
3、当SqlSession关闭或提交后,一级缓存中的数据放到二级缓存中。
注意:CUD执行后不仅会清空一级缓存,还会清空二级缓存。
此博客用log4j进行日志记录!
一、一级缓存
一级缓存是存在于一次数据库会话中的。MyBatis是默认开启一级缓存的。
正常情况:
@Test
public void test01() {
String resource = "mybatis-config.xml";
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession = null;
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession(true); //设置为自动提交
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student1 = studentDao.QueryById(8);
System.out.println(student1);
Student student2 = studentDao.QueryById(8);
System.out.println(student2);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
测试结果:
只发了一次sql语句,说明被一级缓存截获了。
异常情况(一级缓存失效):
1、开启另一个数据库会话,需要重新查询。
@Test
public void test01() {
String resource = "mybatis-config.xml";
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession1 = null, sqlSession2 = null;
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession1 = sqlSessionFactory.openSession(true); //设置为自动提交
StudentDao studentDao1 = sqlSession1.getMapper(StudentDao.class);
sqlSession2 = sqlSessionFactory.openSession(true); //设置为自动提交
StudentDao studentDao2 = sqlSession2.getMapper(StudentDao.class);
Student student1 = studentDao1.QueryById(8);
System.out.println(student1);
Student student2 = studentDao2.QueryById(8);
System.out.println(student2);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession1.close();
sqlSession2.close();
}
}
测试结果:
发了两次sql语句,说明一级缓存失效了。
2、在一次会话中,两次查询中间穿插了增删改操作。
@Test
public void test01() {
String resource = "mybatis-config.xml";
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession1 = null, sqlSession2 = null;
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession1 = sqlSessionFactory.openSession(true); //设置为自动提交
StudentDao studentDao1 = sqlSession1.getMapper(StudentDao.class);
Student student1 = studentDao1.QueryById(8);
System.out.println(student1);
studentDao1.Add(new Student(null, "小花", "12345", 18));
Student student2 = studentDao1.QueryById(8);
System.out.println(student2);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession1.close();
}
}
测试结果:
两次查询中间穿插了一次添加,一级缓存失效了。
3、手动清空了缓存。
@Test
public void test01() {
String resource = "mybatis-config.xml";
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession1 = null, sqlSession2 = null;
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession1 = sqlSessionFactory.openSession(true); //设置为自动提交
StudentDao studentDao1 = sqlSession1.getMapper(StudentDao.class);
Student student1 = studentDao1.QueryById(8);
System.out.println(student1);
sqlSession1.clearCache();
Student student2 = studentDao1.QueryById(8);
System.out.println(student2);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession1.close();
}
}
测试结果:
一级缓存被手动清空了。
二、二级缓存
二级缓存是保存在全局作用域里面的,MyBatis需要手动开启二级缓存。二级缓存要求实体类必须经过序列化,且必须在SqlSession关闭或者提交之后才会起作用。
IDEA快捷生成序列化ID:
IDEA点击File- ->Settings- ->Editor- ->Inspections,输入Serializable class without serialVersionUID
。
应用并重启IDE,双击选中需要序列ID的类再按下Alt+Enter。
在全局配置文件中增加下面配置:
<!-- 开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
在需要开启二级缓存的xml文件中添加cache标签。
<mapper namespace="com.cj.dao.StudentDao">
<cache></cache>
...
</mapper>
@Test
public void test01() {
String resource = "mybatis-config.xml";
SqlSessionFactory sqlSessionFactory = null;
SqlSession sqlSession1 = null, sqlSession2 = null;
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession1 = sqlSessionFactory.openSession(true); //设置为自动提交
StudentDao studentDao1 = sqlSession1.getMapper(StudentDao.class);
sqlSession2 = sqlSessionFactory.openSession(true); //设置为自动提交
StudentDao studentDao2 = sqlSession2.getMapper(StudentDao.class);
Student student1 = studentDao1.QueryById(8);
System.out.println(student1);
sqlSession1.close(); //手动关闭第一次会话
Student student2 = studentDao2.QueryById(8);
System.out.println(student2);
} catch (IOException e) {
e.printStackTrace();
} finally {
sqlSession2.close();
}
}
测试结果:
三、整合第三方缓存(Redis等等)
1、导包。
2、编写第三方缓存的配置文件。
3、在需要用缓存技术相应Dao配置文件中的cache标签中指定使用的缓存种类。