6、延遲加載(mybatis筆記)

一、什么是延遲加載

  • 延遲加載:先從單表查詢(xún)、需要時(shí)再?gòu)年P(guān)聯(lián)表去關(guān)聯(lián)查詢(xún),大大提高數(shù)據(jù)庫(kù)性能。
  • resultMap可以實(shí)現(xiàn)高級(jí)映射(使用association、collection實(shí)現(xiàn)一對(duì)一和一對(duì)多映射),association、collection具備延遲加載的功能。
  • 如果現(xiàn)在的需求:
    查詢(xún)訂單并且關(guān)聯(lián)查詢(xún)用戶(hù)信息。如果先查詢(xún)訂單信息即可滿(mǎn)足要求,當(dāng)我們需要用戶(hù)信息時(shí)再查詢(xún)用戶(hù)信息。把對(duì)用戶(hù)信息的按需查詢(xún)就是延遲加載。

二、使用association實(shí)現(xiàn)延遲加載

需求在上面已經(jīng)給出。(工程mybatis12

2.1 mapper.xml

  • 1.先只查詢(xún)訂單信息
SELECT * FROM orders

在查詢(xún)訂單的statement中使用association去延遲加載(執(zhí)行)下面的statement

  • 2.關(guān)聯(lián)查詢(xún)用戶(hù)信息
    通過(guò)上面查詢(xún)到的訂單信息中的user_id去關(guān)聯(lián)查詢(xún)用戶(hù)信息
SELECT orders.*, 
        (SELECT username FROM USER WHERE orders.`user_id` = user.`id`) username
        (SELECT sex FROM USER WHERE orders.`user_id` = user.`id`)sex 
...
FROM orders

說(shuō)明:上面的sql只是說(shuō)明,語(yǔ)法是不正確的。也就是說(shuō)我們可以通過(guò)訂單信息中的user_id去關(guān)聯(lián)查詢(xún)用戶(hù)的各項(xiàng)信息。

OrdersMapper.xml

<!-- 延遲加載的resultMap -->
<resultMap type="Orders" id="OrdersUserLazyResultMap">
    <!-- 首先需要對(duì)訂單信息進(jìn)行配置 -->
    <id column="id" property="id"/>
    <result column="user_id" property="userId"/>
    <result column="number" property="number"/>
    <result column="createtime" property="createtime"/>
    <result column="note" property="note"/>
    
    <!-- 對(duì)用戶(hù)信息進(jìn)行延遲加載
    select:指定延遲加載要執(zhí)行的sql語(yǔ)句(statement),這里根據(jù)user_id查詢(xún)用戶(hù)信息的statement,
    要使用UserMapper.xml中的findUserById來(lái)完成根據(jù)用戶(hù)id(user_id)的用戶(hù)信息查詢(xún),需要使用命名空間
    column: 訂單信息中關(guān)聯(lián)用戶(hù)信息查詢(xún)的列,是user_id
    關(guān)聯(lián)查詢(xún)的sql理解為
    SELECT orders.*, 
        (SELECT username FROM USER WHERE orders.`user_id` = user.`id`) username
        (SELECT sex FROM USER WHERE orders.`user_id` = user.`id`)sex 
    FROM orders-->
    <association property="user" javaType="User" select="cn.itcast.mapper.UserMapper.findUserById" column="user_id">
    </association>
    
</resultMap>

<!-- 查詢(xún)訂單,關(guān)聯(lián)查詢(xún)用戶(hù),用戶(hù)信息需要延遲加載 -->
<select id="findOrdersUserLazy" resultMap="OrdersUserLazyResultMap">
    SELECT * FROM orders
</select>

說(shuō)明:從上面的注釋中我們可以明確的知道首先我們是查詢(xún)訂單信息(單表),在resultMap中我們使用association的延遲加載功能延遲加載用戶(hù)信息,而用戶(hù)信息的查詢(xún)我們可以使用之前配置過(guò)的查詢(xún)statement
注意:在配置延遲加載的時(shí)候我們使用了之前的查詢(xún)select="cn.itcast.mapper.UserMapper.findUserById",由于不再同一個(gè)mapper.xml中,所以要加上命名空間:
UserMapper.xml

<!-- 查詢(xún),通過(guò)用戶(hù)id進(jìn)行查詢(xún)-->
<select id="findUserById" parameterType="java.lang.Integer" resultType="User">
    SELECT * FROM USER WHERE id = #{value}
</select>

2.2 配置延遲加載功能

延遲加載配置,默認(rèn)是沒(méi)有開(kāi)啟延遲加載的,需要在全局配置文件SqlMapConfig.xmlsettings中進(jìn)行配置。

設(shè)置項(xiàng) 描述 允許值 默認(rèn)值
lazyLoadingEnabled 全局性設(shè)置懶加載。如果設(shè)置為"false",則所有相關(guān)聯(lián)的都會(huì)被初始化加載 true/false false
aggressiveLazyLoading 當(dāng)設(shè)置為"true"的時(shí)候,懶加載的對(duì)象可能被任何懶屬性全部加載。否咋,每個(gè)屬性都按需加載。 true/false true

配置:

<settings>
    <!-- 打開(kāi)延遲加載的開(kāi)關(guān),再將積極加載改為消極加載(即按需加載) -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

2.3 mapper.java

OrdersMapper.java

//查詢(xún)訂單,關(guān)聯(lián)查詢(xún)用戶(hù),其中用戶(hù)信息是延遲加載
public List<Orders> findOrdersUserLazy() throws Exception;

2.4 測(cè)試

OrdersMapperTest.java

//查詢(xún)訂單關(guān)聯(lián)查詢(xún)用戶(hù)信息,其中用戶(hù)信息使用延遲加載
@Test
public void testFindOrdersUserLazy() throws Exception {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //創(chuàng)建代理對(duì)象
    OrdersMapper orders = sqlSession.getMapper(OrdersMapper.class);
    //查詢(xún)訂單信息(單表)
    List<Orders> list = orders.findOrdersUserLazy();
    
    //遍歷上面的訂單列表
    for(Orders order : list){
        User user = order.getUser();//這里實(shí)現(xiàn)按需加載
        System.out.println(user);
    }
    System.out.println(list.size());
    sqlSession.close();
}

說(shuō)明:

  • 1.執(zhí)行上面的mapper接口中的方法,內(nèi)部調(diào)用findOrdersUserLazy,只查詢(xún)orders信息(單表)
  • 2.在程序中去遍歷List<Orders>,當(dāng)我們調(diào)用Orders中的getUser方法時(shí),就開(kāi)始進(jìn)行延遲加載。
  • 3.延遲加載去調(diào)用findUserById這個(gè)方法獲取用戶(hù)信息。
  • 測(cè)試結(jié)果為:
    1

    可以看到當(dāng)用戶(hù)id一樣時(shí),是不會(huì)重復(fù)發(fā)送sql語(yǔ)句的,這就是后面要將的緩存的概念。

2.5 如果我們不使用mybatis提供的延遲加載,我們?nèi)绾螌?shí)現(xiàn)延遲加載?

  • 實(shí)現(xiàn)方法如下:
    定義兩個(gè)mapper方法
      1. 查詢(xún)訂單列表
      1. 根據(jù)用戶(hù)id查詢(xún)用戶(hù)信息
  • 實(shí)現(xiàn)思路:
    先查詢(xún)第一個(gè)mapper的方法得到訂單信息列表,在程序中(service類(lèi)中),按需去調(diào)用第二個(gè)mapper方法去查詢(xún)用戶(hù)信息。當(dāng)然這也是mybatis實(shí)現(xiàn)延遲加載的原理。

總結(jié):使用延遲加載方法,先去查詢(xún)簡(jiǎn)單的sql(最好是單表,也可以是關(guān)聯(lián)查詢(xún)),然后再去按需加載關(guān)聯(lián)查詢(xún)的其他信息。最后對(duì)于collection實(shí)現(xiàn)延遲加載的方式和上面是一樣的,這里不再細(xì)說(shuō)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 主要內(nèi)容: 開(kāi)發(fā)中數(shù)據(jù)模型的分析流程 一對(duì)一查詢(xún) 一對(duì)多查詢(xún) 一、開(kāi)發(fā)中數(shù)據(jù)模型的分析流程 一般在開(kāi)發(fā)中我們會(huì)直接...
    yjaal閱讀 2,253評(píng)論 5 8
  • 非本人總結(jié)的筆記,抄點(diǎn)筆記復(fù)習(xí)復(fù)習(xí)。感謝傳智博客及黑馬程序猿成長(zhǎng) 關(guān)聯(lián)查詢(xún) 數(shù)據(jù)中的表結(jié)構(gòu) 數(shù)據(jù)庫(kù)的分析方法 第一...
    鍵盤(pán)瞎閱讀 1,147評(píng)論 3 5
  • 什么是延遲加載 舉個(gè)例子:如果查詢(xún)訂單并且關(guān)聯(lián)查詢(xún)用戶(hù)信息。如果先查詢(xún)訂單信息即可滿(mǎn)足要求,當(dāng)我們需要查詢(xún)用戶(hù)信息...
    我相信你愛(ài)過(guò)gg閱讀 265評(píng)論 0 0
  • 轉(zhuǎn)載,覺(jué)得這篇寫(xiě) SQLAlchemy Core,寫(xiě)得非常不錯(cuò)。不過(guò)后續(xù)他沒(méi)寫(xiě)SQLAlchemy ORM... ...
    非夢(mèng)nj閱讀 5,591評(píng)論 1 14
  • 您知道什么樣的作息時(shí)間才是符合自然規(guī)律的嗎?冬季最佳的作息時(shí)間表又是怎樣的呢?現(xiàn)在就來(lái)了解吧! 在冬季,我們應(yīng)該早...
    周莫?jiǎng)?chuàng)客閱讀 363評(píng)論 0 1

友情鏈接更多精彩內(nèi)容