# 二級緩存 ###### tags: `Mybatis-緩存` * 二級緩存也被稱作全局緩存,一級緩存作用域太低了,所以誕生了二級緩存 * 基於namespace級別的緩存,一個空間名稱,對應一個二級緩存; **工作機制** * 一個會話查詢一條數據,這個數據就會被放在當前會話的一級緩存中 * 如果當前會話關閉了,這個會話對應的一級緩存就沒了;但是我們想要的式,會話關閉了,一級緩存中的數據被保存到二級緩存中 * 新的會話查詢信息,就可以從二級緩存中獲取內容 * 不同的mapper查出的數據會放在自己對應的緩存(map)中 默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行: ```xml= <cache/> ``` ### 步驟: 1.開啟全局緩存 ```xml= <settings> <!--顯式開啟全局緩存--> <setting name="cacheEnabled" value="true"/> </settings> ``` 2.在要使用二級緩存的Mapper中開啟 ```xml= <cache/> ``` 也可以自定義參數 ```xml= <!--在當前Mapper.xml中使用二級緩存--> <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> ``` 也可以在各別方法中設置 ```xml= <!--useCache:也可以在個別方法中設置--> <select id="queryUserById" resultType="User" useCache="true"> select * from user where id = #{id} </select> ``` 3.測試 (1)二級緩存的應用 ```java= @Test public void test(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.queryUserById(1); System.out.println(user); //需要先關閉,讓緩存保存到二級緩存中 //讓下方的相同mapper查詢相同資料時,直接就可以到二級緩存中取用 sqlSession.close(); SqlSession sqlSession2 = MybatisUtils.getSqlSession(); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); User user2 = mapper2.queryUserById(1); System.out.println(user2); System.out.println(user == user2); sqlSession2.close(); } ``` ![](https://i.imgur.com/dfqky9e.png) (2)二級緩存的失敗 因為尚未相關第一個sqlsession,導致查詢的資料沒有保存到二級緩存中,造成第二次要重新查詢 ```java= @Test public void test(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.queryUserById(1); System.out.println(user); //需要先關閉,讓緩存保存到二級緩存中 //讓下方的相同mapper查詢相同資料時,直接就可以到二級緩存中取用 SqlSession sqlSession2 = MybatisUtils.getSqlSession(); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); User user2 = mapper2.queryUserById(1); System.out.println(user2); System.out.println(user == user2); //第一次sqlSession關閉前,就開始第二次sqlSession的查詢,導致緩存沒有保留到二級緩存池中,因此sqlSession2要重新查詢 sqlSession.close(); sqlSession2.close(); } ``` ![](https://i.imgur.com/tEh3D2O.png) 1.問題:我們需要將實體類序列化,否則就會報錯 ```java= public class User implements Serializable { private int id; private String name; private String pwd; } ``` ### 小結: 1. 只要開啟了二級緩存,在同一個mapper下就有效 2. 所有的數據都會先放在一級緩存中; 3. 只有當會話提交或關閉的時候,才會提交到二級緩存中