MyBatis 查詢結果的緩存


MyBatis的緩存指的是緩存查詢結果,當以后使用相同的sql語句、傳入相同的參數進行查詢時,可直接從mybatis本地緩存中獲取查詢結果,而不必查詢數據庫。

mybatis的緩存包括一級緩存、二級緩存,一級緩存默認是開啟的,二級緩存默認是關閉的。

 

一級緩存:

SqlSession級別,在SqlSession中有一個Map,key是由sql語句、參數等信息組成的唯一值,value是查詢出來的結果對象。

 

二級緩存:

mapper級別,同一個namespace下的mapper,有一個Map。

 

 

 

二級緩存可以使這些sqlSession做到查詢結果共享。

 

 


 

 

一級緩存

一級緩存默認是開啟的。

 

        User user1 = mapper.queryUserById(1);
        User user2 = mapper.queryUserById(1);

第一次查詢時,就將查詢結果放到一級緩存中。

如果后續使用的sql語句相同、傳入的實參也相同,則結果對象也會相同,直接從一級緩存中獲取結果對象,不再查詢數據庫。

 

 

        User user1 = mapper.queryUserById(1);
        sqlSession.commit();
        User user2 = mapper.queryUserById(1);

如果此sqlSession調用了commit()方法,會自動清空此sqlSession的一級緩存。

因為使用commit(),會將修改提交到數據庫,下一次相同的查詢,查詢結果可能變了,之前的一級緩存不能再用,所以會自動清空。

 

 

     User user1 = mapper.queryUserById(1);

        HashMap<String, Object> map = new HashMap<>();
        map.put("username", "張三");
        map.put("id", 1);
        mapper.updateUser(map);

        User user2 = mapper.queryUserById(1);

事實上,只要此sqlSession調用了<update>、<insert>、<delete>這些會修改數據庫的元素,就會清空此sqlSession的一級緩存,不管有沒有使用commit()提交。

 

 


 

 

二級緩存

     SqlSession sqlSession1 = MyBatisUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user1 = mapper1.queryUserById(1);
        System.out.println(user1);

        SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = mapper2.queryUserById(1);
        System.out.println(user2);

不使用二級緩存,會執行2次查詢。

 

 

二級緩存的使用步驟,此處以UserMapper為例:

(1)pojo類要是可序列化的

public class User implements Serializable {
    //......
}

 

 

(2)在mybatis全局配置文件中開啟二級緩存

<settings>
        <setting name="logImpl" value="LOG4J"/>
        <setting name="cacheEnabled" value="true"/>
</settings>

二級緩存默認是關閉的,需要手動開啟。

 

 

(3)在mapper映射文件中指定二級緩存的實現方式,必須顯式指定

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper  PUBLIC
        "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chy.mapper.UserMapper">
    <cache />
    <select id="queryUserById" parameterType="integer" resultType="user">
        SELECT * FROM user_tb WHERE id=#{id}
     </select>
    <update id="updateUser" parameterType="hashmap">
        UPDATE user_tb SET username=#{username} WHERE id=#{id}
    </update>
</mapper>

 

完整寫法:

<cache type="perpetualCache" />

type指定二級緩存的實現方式,缺省type時默認使用mybatis自帶的perpetualCache。

 

 

(4)需要調用close()關閉sqlSession,才會將此sqlSession的查詢結果(一級緩存)寫入到二級緩存中

     SqlSession sqlSession1 = MyBatisUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user1 = mapper1.queryUserById(1);
        System.out.println(user1);
        sqlSession1.close(); 
        SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = mapper2.queryUserById(1);
        System.out.println(user2);

只執行1次查詢。后續使用相同sql語句、傳入相同的實參進行查詢時,直接從二級緩存中獲取結果對象。

 

 

提交修改時,會清空整個二級緩存:

     SqlSession sqlSession1 = MyBatisUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user1 = mapper1.queryUserById(1);
        System.out.println(user1);

        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("username", "j");
        hashMap.put("id", 1);
        mapper1.updateUser(hashMap);
        sqlSession1.commit();

        SqlSession sqlSession2 = MyBatisUtils.getSqlSession();
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = mapper2.queryUserById(2);
        System.out.println(user2);

 

只寫了commit()、實際沒有調用<insert> | <update> | <delete>,不會清空二級緩存,反而會將之前查詢結果寫入到二級緩存。

寫了commit()、有調用<insert> | <update> | <delete>,會清空整個二級緩存。

先后調用commit()、close(),不會寫入二級緩存,因為commit()的存在,反而會清空整個二級緩存。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM