MyBatis的緩存,包括一級緩存,二級緩存。
什么是一級緩存?
一級緩存指的就是sqlsession,在sqlsession中有一個數據區域,是map結構,這個區域就是一級緩存區域。一級緩存中的key是由sql語句、條件、statement等信息組成一個唯一值。一級緩存中的value,就是查詢出的結果對象。
什么是二級緩存?
二級緩存指的就是同一個namespace下的mapper,二級緩存中,也有一個map結構,這個區域就是一級緩存區域。一級緩存中的key是由sql語句、條件、statement等信息組成一個唯一值。一級緩存中的value,就是查詢出的結果對象。
一級緩存是默認使用的。
二級緩存需要手動開啟。
MyBatis緩存框架圖
MyBatis緩存框架圖
一級緩存原理圖
代碼測試:
/**
* 測試一級緩存
* @throws Exception
*/
@Test
public void testSelectStudentById() throws Exception {
SqlSession session1 = sqlSessionFactory.openSession();
// 拿到代理對象
StudentMapper mapper = session1.getMapper(StudentMapper.class);
//第一次查詢id為1的Student的信息
Student student1 = mapper.selectStudentById(1);
System.out.println(student1);
//第二次查詢時,發現緩存中有id為1的Student的信息,于是從緩存中讀取
Student student2 = mapper.selectStudentById(1);
System.out.println(student2);
session1.close();
}
然后debug看一下
再回頭看一下上面一級緩存原理圖中間那一部分,當修改刪除更新時commit,會自動清空緩存
代碼測試:
/**
* 測試一級緩存
* @throws Exception
*/
@Test
public void testSelectStudentById() throws Exception {
SqlSession session1 = sqlSessionFactory.openSession();
// 拿到代理對象
StudentMapper mapper = session1.getMapper(StudentMapper.class);
//第一次查詢id為1的Student的信息
Student student1 = mapper.selectStudentById(1);
System.out.println(student1);
//更新操作
student1.setName("RonaldoWang");
mapper.updateStudent(student1);
//commit()就會清空緩存
session1.commit();
//第二次查詢時,發現緩存中有id為1的Student的信息,于是從緩存中
Student student2 = mapper.selectStudentById(1);
System.out.println(student2);
session1.close();
}
測試結果:
二級緩存原理圖
看起來二級緩存與一級緩存相似,只是二級緩存的范圍更廣,區域劃分是namespace,而一級緩存是在sqlsession里面。
1.開啟二級緩存
第一步:總開關開啟,需要在sqlMapConfig.xml中通過settings標簽開啟,默認它就是開啟的,但還是寫上去比較好,容易閱讀吧。
第二步:在Mapper.xml下namespace中開啟自己的開關
第三步:在PO類中實現序列化操作。
)
之所以需要實現序列化接口,是因為方便反序列化,二級緩存的區域不一定只是在內存中,也有可能在硬盤中。
測試代碼:
/**
* 測試二級緩存
* @throws Exception
*/
@Test
public void testSelectStudentById() throws Exception {
SqlSession session1 = sqlSessionFactory.openSession();
SqlSession session2 = sqlSessionFactory.openSession();
SqlSession session3 = sqlSessionFactory.openSession();
StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
StudentMapper mapper2 = session2.getMapper(StudentMapper.class);
StudentMapper mapper3 = session2.getMapper(StudentMapper.class);
Student student1 = mapper1.selectStudentById(1);
System.out.println(student1);
//這里close很關鍵,在二級緩存中,close()會將數據放到二級緩存中
session1.close();
Student student3 = mapper3.selectStudentById(1);
System.out.println(student3);
session3.close();
}
測試結果:
上面代碼中session2,和mapper2還沒有用到,這里可以用mapper2給數據更新一下,看看是否會將緩存清空?
測試代碼
/**
* 測試二級緩存
* @throws Exception
*/
@Test
public void testSelectStudentById() throws Exception {
SqlSession session1 = sqlSessionFactory.openSession();
SqlSession session2 = sqlSessionFactory.openSession();
SqlSession session3 = sqlSessionFactory.openSession();
StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
StudentMapper mapper2 = session2.getMapper(StudentMapper.class);
StudentMapper mapper3 = session3.getMapper(StudentMapper.class);
Student student1 = mapper1.selectStudentById(1);
System.out.println(student1);
//這里close很關鍵,在二級緩存中,close()會將數據放到二級緩存中
session1.close();
Student student2 = mapper2.selectStudentById(1);
student2.setName("小六子");
mapper2.updateStudent(student2);
session2.commit();
session2.close();
Student student3 = mapper3.selectStudentById(1);
System.out.println(student3);
session3.close();
}
測試結果:
圈出來的看看就能理解了。
禁用緩存
)
刷新緩存
刷新緩存在select語句中默認是false