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">