關於mybatis中的緩存機制

什麼是緩存?

存在於內存中的臨時數據

爲什麼使用緩存?

可以減少和數據庫交互的次數,提高執行效率

什麼樣的數據能使用緩存?

適用於緩存 經常查詢,並且不經常改變。數據的正確與否對最終結果影響不大的
不適用於緩存 經常改變的數據,以及數據的正確與否對最終結果影響很大。例如:商品的庫存,銀行的匯率,股市的股價

mybatis中的一級緩存和二級緩存

一級緩存

指的是mybatis中Sqlsession對象的緩存,當我們執行查詢之後,查詢的結果會同時存入到sqlsession爲我們提供的一塊區域中,該區域的結構是一個map,當我們再次查詢同樣的數據,mybatis會先去sqlsession中查詢是否有,有的話直接拿出來用。當sqlsession對象消失時,mybatis的一級緩存就消失了

public class MybatisTest {
    private InputStream in;
    private SqlSession sqlSession;
    private SqlSessionFactory factory;
    private IUserDao userDao;
    @Before//用於在測試方法執行之前執行
    public void init() throws Exception{
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        //創建sqlsession時傳遞一個true參數則會自動提交事物
        sqlSession = factory.openSession(true);
        userDao = sqlSession.getMapper(IUserDao.class);
    }
    @After//用於在測試方法執行之後執行
    public void destory() throws Exception{
        //提交事物
        //sqlSession.commit();
        sqlSession.close();
        in.close();
    }
    @Test
    public void testFirstLevelCache(){
        User user1 = userDao.findById(41);
        System.out.println(user1);
        User user2 = userDao.findById(41);
        System.out.println(user2);
        System.out.println(user1 == user2);
    }
}

在這裏插入圖片描述
可以從執行結果中發現,只執行了一次查詢。而且產生的兩個對象是同一個。第二次就是從緩存中查詢的

/**
     *  關閉sqlSession並重新打開
     */
    @Test
    public void testFirstLevelCache(){
        User user1 = userDao.findById(41);
        System.out.println(user1);
       // sqlSession.close()
       //此方法也可以清空緩存
       sqlSession.clearCache();;
        //再次開啓sqlsession對象
        sqlSession = factory.openSession();
        userDao = sqlSession.getMapper(IUserDao.class);
        User user2 = userDao.findById(41);
        System.out.println(user2);
        System.out.println(user1 == user2);
    }

在這裏插入圖片描述
可以發現,執行了兩次查詢。而且兩次查詢的對象不是同一個,可以看出,將sqlsession關閉之後,緩存就消失了。
一級緩存是 SqlSession 範圍的緩存,當調用 SqlSession 的修改,添加,刪除,commit(),close()等方法時,就會清空一級緩存。

    @Test
    public void testClearCache(){
        //1.根據id查詢用戶
        User user1 = userDao.findById(41);
        System.out.println(user1);
        //2.更新用戶信息
        user1.setUsername("uucc");
        user1.setAddress("北京市海淀區");
        userDao.updateUser(user1);
        //3.再次查詢id爲41的用戶
        User user2 = userDao.findById(41);
        System.out.println(user2);
        System.out.println(user2 == user1);

    }

在這裏插入圖片描述
在這裏插入圖片描述
第一次發起查詢用戶 id 爲 1 的用戶信息,先去找緩存中是否有 id 爲 1 的用戶信息,如果沒有,從數據庫查
詢用戶信息。得到用戶信息,將用戶信息存儲到一級緩存中。
如果 sqlSession 去執行 commit 操作(執行插入、更新、刪除),清空 SqlSession 中的一級緩存,這樣
做的目的爲了讓緩存中存儲的是最新的信息,避免髒讀。
第二次發起查詢用戶 id 爲 1 的用戶信息,先去找緩存中是否有 id 爲 1 的用戶信息,緩存中有,直接從緩存
中獲取用戶信息。

二級緩存

它指定是Mybatis中SqlSessionFactory對象的緩存,由同一個SqlSessionFactory對象創建的SqlSession共享其緩存
在這裏插入圖片描述
二級緩存的使用步驟:
第一步,讓mybatis框架支持二級緩存(在SqlMapConfig.xml中配置)

<!-- 全局的開啓配置文件中的所有已經配置的任何緩存 -->
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
第二步,讓當前的映射文件支持二級緩存(在IUserDao.xml中配置)
<!-- 開啓user支持二級緩存 -->
    <cache/>
第三步:讓當前的操作支持二級緩存(在select標籤中配置)
<!-- 根據id查詢用戶 -->
    <select id="findById" parameterType="INT" resultType="com.echo.domain.User" useCache="true">
        select * from user where id = #{id}
    </select>

測試

@Test
    public void testFirstLevelCache(){
        SqlSession sqlSession1 = factory.openSession();
        IUserDao iUserDao1 = sqlSession1.getMapper(IUserDao.class);
        User user1 = iUserDao1.findById(41);
        System.out.println(user1);
        //一級緩存消失
        sqlSession1.close();

        SqlSession sqlSession2 = factory.openSession();
        IUserDao iUserDao2 = sqlSession2.getMapper(IUserDao.class);
        User user2 = iUserDao2.findById(41);
        System.out.println(user1);
        sqlSession2.close();

        System.out.println(user1 == user2);
    }

結果
在這裏插入圖片描述
最後打印爲false原因是二級緩存中存放的是數據而不是對象
在二級緩存中存放的是諸如
{“id”:41,“username”:“老王”,“address”:“北京”}類型的數據
誰用時就將數據拿過來,之後創建一個新的用戶,將數據填充到新的用戶對象中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章