Mybatis提供查詢緩存,若是緩存中有數據就不用從數據庫中獲取,用於減輕數據壓力,提升系統性能。java
Mybatis的查詢緩存總共有兩級,咱們稱之爲一級緩存和二級緩存:mysql
Mybatis默認開啓了一級緩存spring
說明:sql
@Test public void testOneLevelCache() { SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 第一次查詢ID爲1的用戶,去緩存找,找不到就去查找數據庫 User user1 = mapper.findUserById(1); System.out.println(user1); // 第二次查詢ID爲1的用戶 User user2 = mapper.findUserById(1); System.out.println(user2); sqlSession.close(); }
@Test public void testOneLevelCache() { SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 第一次查詢ID爲1的用戶,去緩存找,找不到就去查找數據庫 User user1 = mapper.findUserById(1); System.out.println(user1); User user = new User(); user.setUsername("隔壁老詹1"); user.setAddress("洛杉磯湖人"); //執行增刪改操做,清空緩存 mapper.insertUser(user); // 第二次查詢ID爲1的用戶 User user2 = mapper.findUserById(1); System.out.println(user2); sqlSession.close(); }
正式開發,是將mybatis和spring進行整合開發,事務控制在service中。數據庫
一個service方法中包括 不少mapper方法調用:緩存
service{ //開始執行時,開啓事務,建立SqlSession對象 //第一次調用mapper的方法findUserById(1) //第二次調用mapper的方法findUserById(1),從一級緩存中取數據 //方法結束,sqlSession關閉 }
若是是執行兩次service調用查詢相同 的用戶信息,是不走一級緩存的,由於mapper方法結束,sqlSession就關閉,一級緩存就清空。數據結構
二級緩存是mapper(namespace)級別的。mybatis
說明:app
Mybatis默認是沒有開啓二級緩存,開啓步驟以下:性能
<!-- 開啓二級緩存總開關 --> <settings> <setting name="cacheEnabled" value="true"/> </settings>
<!-- 開啓本mapper下的namespace的二級緩存,默認使用的是mybatis提供的PerpetualCache --> <cache></cache>
因爲二級緩存的數據不必定都是存儲到內存中,它的存儲介質多種多樣,好比說存儲到文件系統中,因此須要給緩存的對象執行序列化。若是該類存在父類,那麼父類也要實現序列化。
@Test public void testTwoLevelCache() { SqlSession sqlSession1 = sqlSessionFactory.openSession(); SqlSession sqlSession2 = sqlSessionFactory.openSession(); SqlSession sqlSession3 = sqlSessionFactory.openSession(); UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); UserMapper mapper3 = sqlSession3.getMapper(UserMapper.class); // 第一次查詢ID爲1的用戶,去緩存找,找不到就去查找數據庫 User user1 = mapper1.findUserById(1); System.out.println(user1); // 關閉SqlSession1 sqlSession1.close(); // 第二次查詢ID爲1的用戶 User user2 = mapper2.findUserById(1); System.out.println(user2); // 關閉SqlSession2 sqlSession2.close(); }
@Test public void testTwoLevelCache() { SqlSession sqlSession1 = sqlSessionFactory.openSession(); SqlSession sqlSession2 = sqlSessionFactory.openSession(); SqlSession sqlSession3 = sqlSessionFactory.openSession(); UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); UserMapper mapper3 = sqlSession3.getMapper(UserMapper.class); // 第一次查詢ID爲1的用戶,去緩存找,找不到就去查找數據庫 User user1 = mapper1.findUserById(1); System.out.println(user1); // 關閉SqlSession1 sqlSession1.close(); //修改查詢出來的user1對象,做爲插入語句的參數 user1.setUsername("隔壁老詹1"); user1.setAddress("洛杉磯湖人"); mapper3.insertUser(user1); // 提交事務 sqlSession3.commit(); // 關閉SqlSession3 sqlSession3.close(); // 第二次查詢ID爲1的用戶 User user2 = mapper2.findUserById(1); System.out.println(user2); // 關閉SqlSession2 sqlSession2.close(); }
默認二級緩存的粒度是Mapper級別的,可是若是在同一個Mapper文件中某個查詢不想使用二級緩存的話,就須要對緩存的控制粒度更細。
在select標籤中設置useCache=false,能夠禁用當前select語句的二級緩存,即每次查詢都是去數據庫中查詢,默認狀況下是true,即該statement使用二級緩存。
<select id="findUserById" parameterType="int" resultType="com.kkb.mybatis.po.User" useCache="true"> SELECT * FROM user WHERE id = #{id} </select>
經過flushCache屬性,能夠控制select、insert、update、delete標籤的是否屬性二級緩存
默認設置
默認配置解讀
flushCache設置以下:
<select id="findUserById" parameterType="int" resultType="com.kkb.mybatis.po.User" useCache="true" flushCache="true"> SELECT * FROM user WHERE id = #{id} </select>
對於訪問響應速度要求高,可是實時性不高的查詢,能夠採用二級緩存技術。
在使用二級緩存的時候,要設置一下刷新間隔(cache標籤中有一個flashInterval屬性)來定時刷新二級緩存,這個刷新間隔根據具體需求來設置,好比設置30分鐘、60分鐘等,單位爲毫秒。
Mybatis二級緩存對細粒度的數據級別的緩存實現很差。
對商品信息進行緩存,因爲商品信息查詢訪問量大,可是要求用戶每次查詢都是最新的商品信息,此時若是使用二級緩存,就沒法實現當一個商品發生變化只刷新該商品的緩存信息而不刷新其餘商品緩存信息,由於二級緩存是mapper級別的,當一個商品的信息發送更新,全部的商品信息緩存數據都會清空。
此類問題,須要在業務層根據須要對數據有針對性的緩存。
好比能夠對常常變化的 數據操做單獨放到另外一個namespace的mapper中。