MyBatis延遲加載,一級緩存,二級緩存

MyBatis延遲加載,一級緩存,二級緩存

Ennio

延遲加載配置:

什麼時候用延遲加載?比如現在有班級和學生表,一對多關係,你可能只需要班級的信息,而不需要該班級學生的信息,這時候可以進行配置,讓查詢時先查詢到班級的信息,在之後需要學生信息時候,再進行查詢,避免不必要的查詢。

需要進行如下配置:這裏以一對多爲例,其他關係類似:

PersonMapping.xml

    <select id="selectPersonByClassId" resultMap="class_person_map" parameterType="int">
        select * from class where classId=#{id}
    </select>
    <resultMap id="class_person_map" type="class">
        <id column="classId" property="classId"/>
        <result property="number" column="number"/>
        <collection property="persons" ofType="person" select="mappers.ClassMapper.queryPersonByClassId" column="classId">
        </collection>
    </resultMap>

注意我們的映射,只映射了班級id和班級Number兩個信息,並沒有映射學生信息,而是通過<cllection>來配置的,標籤屬性

select:當需要persons屬性時,執行select值所對應的id的sql語句進行查詢(mappers.ClassMapper,xml)

column:執行sql語句時傳入的參數

mappers.ClassMapper.xml

當需要班級學生信息時,會通過select屬性來尋找到指定id的sql語句查詢,如下

    <select id="queryPersonByClassId" parameterType="int" resultType="Person">
        select * from person where classId=#{classid}
    </select>

之後設置斷點調試可以看到只有調用了Class.getPersons()方法纔會執行查詢學生的sql語句。

一級緩存:

當通過一個SqlSession對象查詢到一個數據時,MyBatis會將該數據放入該sqlsession當中,當下一次再次查詢該數據時,會從該sqlsession直接取得該數據,不需要再與數據庫交互查詢,自動開啓。不過注意第二次查詢必須也是在同一個SQLSESSION之下進行的。

二級緩存:

myBatis內置的:

接上面,通過一個SQLSession對象查詢到了一個數據,不僅會放入一級緩存,還會放入二級緩存當中。當你下一次通過另一個不同的SQLSEssion對象查詢相同的數據時,會從二級緩存當中進行獲取,不過查詢時SQLSession必來自同一個mapper.class。

總的來說兩句話:一級緩存同一個sqlsession,二級緩存同一個mapper.class初始化的,即同一個namespace,是否進入緩存就是依據這個判斷的。

開啓配置方式:

config.xml:

<setting name="cacheEnabled" value="true"/>

mapper,xml

<cache/>

另外二級緩存是將數據進行序列化的,所以必要要讓開啓二級緩存的對象繼承序列化接口才行。序列化就是將數據從內存放入到硬盤之中。

即給mapper.xml對應的指定class  加上

implements Serializable

而且如果當前mapper對應的class繼承了其他類或者裏面有級聯屬性,其他類或者級聯屬性也必須要序列化。

相當於序列化三個:本類,父類,級聯屬性  

一級緩存二級緩存的緩存時機:

一級緩存只要查詢了就放入一級緩存當中,相當於是實時的,

二級緩存是在一個sqlsession.close()之後纔會將該sqlsession所查詢到的放入到二級緩存當中。

示例:

        //加載配置信息
        Reader reader = Resources.getResourceAsReader("config.xml");
        //connection
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
     //第一個sqlsession
        SqlSession sqlSession = sessionFactory.openSession();
        PersonMapping personMapping = sqlSession.getMapper(PersonMapping.class);
        personMapping.selectPersonById(2);
        System.out.println("---");
        sqlSession.close();
     //第二個sqlsession
        SqlSession sqlSession2 = sessionFactory.openSession();
        PersonMapping personMapping2 = sqlSession2.getMapper(PersonMapping.class);
        personMapping2.selectPersonById(2);
        sqlSession2.close();

執行後,查看日誌可以看到只執行了一條sql語句,PersonMapping.class共享同一個二級緩存

清理緩存:commit()會清除緩存(一級二級都是的),另外注意這個commit()不能是查詢自身的commit,即這個commit所屬於的sqlsession對象必須是執行了增刪改的sqlsession。

 

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