一、MyBatis一級緩存
MyBatis默認啟動一級緩存,一級緩存是SqlSession級別的
注意:有兩個因素會使一級緩存失效:
1.對SqlSession進行commit()操作(即對數據庫進行了增、刪、改操作)。數據庫中的數據發生了改變,此時若再從內存中讀取緩存的數據,則會讀取到錯誤的數據信息,所以此時舊的一級緩存中的數據會清空,當用戶下一次執行查詢操作時,會重新從數據庫中讀取數據並放入一級緩存中
2.關閉SqlSession。一級緩存的設計是每個sqlsession單獨使用一個緩存空間,不同的sqlsession是不能互相訪問數據的。當然,在SqlSession關閉后,其中數據自然被清空。由此可以看出,一級緩存是SqlSession級別的
測試一:
第一次查詢時ID為2,第二次ID為3,第三次查詢時ID又為3,運行程序,通過log4j日志得知,獲得了3個結果,但是ID為2的SQL語句只執行了一次,第二次ID為2的SQL語句與第一次相同,直接從緩存中獲取結果,而沒有再次執行id=2的SQL語句。
SqlSession sqlSession1=DbUtil.getSqlSession(); //這里自己編寫了一個DbUtil工具類,其下有一個getSqlSession()的靜態方法,由SqlSessionFactory的openSession()方法獲得並返回一個SqlSession對象
UserMapper userMapper1=sqlSession1.getMapper(UserMapper.class);
System.out.println(userMapper1.findUserById(2)); //findUserById(int id)是UserMapper接口中的方法
System.out.println(userMapper1.findUserById(3));
System.out.println(userMapper1.findUserById(2));
測試二:
sqlSession1.close();/**一旦關閉了sqlSession1,開啟一個新的sqlSession2,那么sqlSession1的一級緩存失效,相同的ID為2的查詢語句本次也會執行,在日志記錄中會看到執行了兩次select*from users where user_id=2的語句**/
SqlSession sqlSession2=DbUtil.getSqlSession();
UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
System.out.println(userMapper2.findUserById(2));
二、MyBatis二級緩存
一級緩存的作用域僅限於一個sqlsession,而二級緩存的作用域是一個namespace。但並不是意味着同一個namespace創建的mapper可以互相讀取緩存內容,
這里的原則是,如果開啟了二級緩存,那么在關閉sqlsession后,會把該sqlsession一級緩存中的數據添加到namespace的二級緩存中。
開啟二級緩存的步驟:
1.打開二級緩存總開關
打開總開關,只需要在mybatis總配置文件中加入一行設置
<settings> <!--開啟二級緩存--> <setting name="cacheEnabled" value="true"/> </settings>
2.打開需要使用二級緩存的mapper的開關
在需要開啟二級緩存的mapper.xml(比如UserMapper.xml)中加入cache標簽
<cache/>
3.POJO序列化
讓需要使用二級緩存的POJO類實現Serializable接口,如
public class User implements Serializable {
}
在開啟二級緩存之后,再次執行之前測試中的代碼,會發現即使sqlSession1.close()之后,再重新獲得新的SqlSession sqlSession2=DbUtil.getSqlSession(),然后再次執行相同的SQL操作,查詢ID為2的用戶,如下:
UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
System.out.println(userMapper2.findUserById(2));
最終會發現在日志記錄中只執行了一次
select*from users where user_id=2的語句,證明二級緩存開啟成功!
必須注意的是:
即使開啟了二級緩存,不同的sqlsession之間的緩存數據也不是想互訪就能互訪的,必須等到sqlsession關閉了以后,才會把其一級緩存中的數據寫入二級緩存
如果把之前的sqlSession1.close()注釋掉,那么同樣會執行兩次select*from users where user_id=2的SQL語句,因為sqlSession1沒有關閉,一級緩存中的數據並沒寫入二級緩存,
而sqlSession2又無法訪問sqlSession1的一級緩存中的數據,所以會重新執行該查詢語句。