MyBatis緩存通俗易懂
1.1 mybatis緩存介紹
如下圖,是mybatis一級緩存和二級緩存的區別圖解:
Mybatis一級緩存的作用域是同一個SqlSession,在同一個sqlSession中兩次執行相同的sql語句,第一次執行完畢會將數據庫中查詢的數據寫到緩存(內存),第二次會從緩存中獲取數據將不再從數據庫查詢,從而提高查詢效率。當一個sqlSession結束後該sqlSession中的一級緩存也就不存在了。當遇到增刪改時會清空緩存。Mybatis默認開啟一級緩存。
Mybatis二級緩存是多個SqlSession共享的,其作用域是mapper的同一個namespace,不同的sqlSession兩次執行相同namespace下的sql語句且向sql中傳遞參數也相同即最終執行相同的sql語句,第一次執行完畢會將數據庫中查詢的數據寫到緩存(內存),第二次會從緩存中獲取數據將不再從數據庫查詢,從而提高查詢效率。當遇到增刪改時會清空緩存。Mybatis默認沒有開啟二級緩存需要在setting全局參數中配置開啟二級緩存。
1.2 一級緩存
1.2.1 原理
下圖是根據id查詢用戶的一級緩存圖解:
一級緩存區域是根據SqlSession為單位劃分的。
每次查詢會先從緩存區域找,如果找不到從數據庫查詢,查詢到數據將數據寫入緩存。
Mybatis內部存儲緩存使用一個HashMap,key為hashCode+sqlId+Sql語句。value為從查詢出來映射生成的java對象
sqlSession執行insert、update、delete等操作commit提交後會清空緩存區域。
1.2.2 測試1
//獲取session SqlSession session = sqlSessionFactory.openSession();//獲限mapper接口實例 UserMapper userMapper = session.getMapper(UserMapper.class); //第一次查詢 User user1 = userMapper.findUserById(1); System.out.println(user1); //第二次查詢,由於是同一個session則不再向數據發出語句直接從緩存取出 User user2 = userMapper.findUserById(1); System.out.println(user2);//關閉session session.close();
1.2.3 測試2
//獲取session SqlSession session = sqlSessionFactory.openSession(); //獲限mapper接口實例 UserMapper userMapper = session.getMapper(UserMapper.class); //第一次查詢 User user1 = userMapper.findUserById(1); System.out.println(user1); //在同一個session執行更新 User user_update = new User(); user_update.setId(1); user_update.setUsername("李奎"); userMapper.updateUser(user_update); session.commit(); //第二次查詢,雖然是同一個session但是由於執行了更新操作session的緩存被清空,這裏重新發出sql操作 User user2 = userMapper.findUserById(1); System.out.println(user2);
1.3 二級緩存
1.3.1 原理
下圖是多個sqlSession請求UserMapper的二級緩存圖解。
二級緩存區域是根據mapper的namespace劃分的,相同namespace的mapper查詢數據放在同一個區域,如果使用mapper代理方法每個mapper的namespace都不同,此時可以理解為二級緩存區域是根據mapper劃分。
每次查詢會先從緩存區域找,如果找不到從數據庫查詢,查詢到數據將數據寫入緩存。
Mybatis內部存儲緩存使用一個HashMap,key為hashCode+sqlId+Sql語句。value為從查詢出來映射生成的java對象
sqlSession執行insert、update、delete等操作commit提交後會清空緩存區域。
1.3.2 開啟二級緩存:
在核心配置文件SqlMapConfig.xml中加入
<setting name="cacheEnabled" value="true"/>
描述 |
允許值 |
默認值 |
|
cacheEnabled |
對在此配置文件下的所有cache 進行全局性開/關設置。 |
true false |
true |
要在你的Mapper映射文件中添加一行: <cache /> ,表示此mapper開啟二級緩存。
1.3.3 實現序列化
二級緩存需要查詢結果映射的pojo對象實現java.io.Serializable接口實現序列化和反序列化操作,註意如果存在父類、成員pojo都需要實現序列化接口。
public class Orders implements Serializable
public class User implements Serializable
....
1.3.4 測試
//獲取session1 SqlSession session1 = sqlSessionFactory.openSession(); UserMapper userMapper = session1.getMapper(UserMapper.class); //使用session1執行第一次查詢 User user1 = userMapper.findUserById(1); System.out.println(user1); //關閉session1 session1.close(); //獲取session2 SqlSession session2 = sqlSessionFactory.openSession(); UserMapper userMapper2 = session2.getMapper(UserMapper.class); //使用session2執行第二次查詢,由於開啟了二級緩存這裏從緩存中獲取數據不再向數據庫發出sql User user2 = userMapper2.findUserById(1); System.out.println(user2); //關閉session2 session2.close();
1.3.5 禁用二級緩存
在statement中設置useCache=false可以禁用當前select語句的二級緩存,即每次查詢都會發出sql去查詢,默認情況是true,即該sql使用二級緩存。
<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
1.3.6 刷新緩存
在mapper的同一個namespace中,如果有其它insert、update、delete操作數據後需要刷新緩存,如果不執行刷新緩存會出現臟讀。
設置statement配置中的flushCache="true" 屬性,默認情況下為true即刷新緩存,如果改成false則不會刷新。使用緩存時如果手動修改數據庫表中的查詢數據會出現臟讀。
如下:
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">
MyBatis緩存通俗易懂