1. 程式人生 > >MyBatis緩存通俗易懂

MyBatis緩存通俗易懂

不同 傳遞 lis true align 提交 session共享 style left

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緩存通俗易懂