亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

通過(guò)項(xiàng)目逐步深入了解Mybatis(四)

kuangcaibao / 905人閱讀

摘要:相關(guān)閱讀通過(guò)項(xiàng)目逐步深入了解一通過(guò)項(xiàng)目逐步深入了解二通過(guò)項(xiàng)目逐步深入了解三本項(xiàng)目所有代碼及文檔都托管在地址延遲加載什么是延遲加載可以實(shí)現(xiàn)高級(jí)映射使用實(shí)現(xiàn)一對(duì)一及一對(duì)多映射,具備延遲加載功能。一級(jí)緩存是級(jí)別的緩存。

相關(guān)閱讀:

1、通過(guò)項(xiàng)目逐步深入了解Mybatis<一>

2、通過(guò)項(xiàng)目逐步深入了解Mybatis<二>

3、通過(guò)項(xiàng)目逐步深入了解Mybatis<三>

本項(xiàng)目所有代碼及文檔都托管在 Github地址:https://github.com/zhisheng17/mybatis

延遲加載 什么是延遲加載?

resultMap可以實(shí)現(xiàn)高級(jí)映射(使用association、collection實(shí)現(xiàn)一對(duì)一及一對(duì)多映射),association、collection具備延遲加載功能。
需求:
如果查詢訂單并且關(guān)聯(lián)查詢用戶信息。如果先查詢訂單信息即可滿足要求,當(dāng)我們需要查詢用戶信息時(shí)再查詢用戶信息。把對(duì)用戶信息的按需去查詢就是延遲加載。

延遲加載:先從單表查詢、需要時(shí)再?gòu)年P(guān)聯(lián)表去關(guān)聯(lián)查詢,大大提高 數(shù)據(jù)庫(kù)性能,因?yàn)椴樵儐伪硪汝P(guān)聯(lián)查詢多張表速度要快。

打開(kāi)延遲加載開(kāi)關(guān)

在mybatis核心配置文件中配置:

lazyLoadingEnabled、aggressiveLazyLoading

設(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

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

需求:查詢訂單并且關(guān)聯(lián)查詢用戶信息

Mapper.xml

需要定義兩個(gè) mapper 的方法對(duì)應(yīng)的 statement。

1、只查詢訂單信息

SQL 語(yǔ)句: select * from orders

在查詢訂單的 statement 中使用 association 去延遲加載(執(zhí)行)下邊的 statement (關(guān)聯(lián)查詢用戶信息)


    

2、關(guān)聯(lián)查詢用戶信息

通過(guò)上面查詢訂單信息中的 user_id 來(lái)關(guān)聯(lián)查詢用戶信息。使用 UserMapper.xml 中的 findUserById

SQL語(yǔ)句:select * from user where id = user_id

上邊先去執(zhí)行 findOrdersUserLazyLoading,當(dāng)需要去查詢用戶的時(shí)候再去執(zhí)行 findUserById ,通過(guò) resultMap的定義將延遲加載執(zhí)行配置起來(lái)。也就是通過(guò) resultMap 去加載 UserMapper.xml 文件中的 select = findUserById

延遲加載的 resultMap

    
        
        
        
        
        
        
        
        
        
    
OrderMapperCustom.java
public List findOrdersUserLazyLoading() throws Exception;
測(cè)試代碼:
@Test
    public void testFindOrdersUserLazyLoading() throws Exception
    {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //創(chuàng)建OrdersMapperCustom對(duì)象,mybatis自動(dòng)生成代理對(duì)象
        OrdersMapperCustom ordersMapperCustom = sqlSession.getMapper(OrdersMapperCustom.class);
        //查詢訂單信息
        List list = ordersMapperCustom.findOrdersUserLazyLoading();
        //遍歷所查詢的的訂單信息
        for (Orders orders : list)
        {
            //查詢用戶信息
            User user = orders.getUser();
            System.out.println(user);
        }
        sqlSession.close();
    }
測(cè)試結(jié)果:

整個(gè)延遲加載的思路:

1、執(zhí)行上邊mapper方法(findOrdersUserLazyLoading),內(nèi)部去調(diào)用cn.zhisheng.mybatis.mapper.OrdersMapperCustom 中的 findOrdersUserLazyLoading 只查詢 orders 信息(單表)。

2、在程序中去遍歷上一步驟查詢出的 List,當(dāng)我們調(diào)用 Orders 中的 getUser 方法時(shí),開(kāi)始進(jìn)行延遲加載。

3、延遲加載,去調(diào)用 UserMapper.xml 中 findUserbyId 這個(gè)方法獲取用戶信息。

思考:

不使用 mybatis 提供的 association 及 collection 中的延遲加載功能,如何實(shí)現(xiàn)延遲加載??

實(shí)現(xiàn)方法如下:

定義兩個(gè)mapper方法:

1、查詢訂單列表

2、根據(jù)用戶id查詢用戶信息

實(shí)現(xiàn)思路:

先去查詢第一個(gè)mapper方法,獲取訂單信息列表

在程序中(service),按需去調(diào)用第二個(gè)mapper方法去查詢用戶信息。

總之:

使用延遲加載方法,先去查詢 簡(jiǎn)單的 sql(最好單表,也可以關(guān)聯(lián)查詢),再去按需要加載關(guān)聯(lián)查詢的其它信息。

一對(duì)多延遲加載

上面的那個(gè)案例是一對(duì)一延遲加載,那么如果我們想一對(duì)多進(jìn)行延遲加載呢,其實(shí)也是很簡(jiǎn)單的。

一對(duì)多延遲加載的方法同一對(duì)一延遲加載,在collection標(biāo)簽中配置select內(nèi)容。

延遲加載總結(jié):

作用:

當(dāng)需要查詢關(guān)聯(lián)信息時(shí)再去數(shù)據(jù)庫(kù)查詢,默認(rèn)不去關(guān)聯(lián)查詢,提高數(shù)據(jù)庫(kù)性能。
只有使用resultMap支持延遲加載設(shè)置。

場(chǎng)合:

當(dāng)只有部分記錄需要關(guān)聯(lián)查詢其它信息時(shí),此時(shí)可按需延遲加載,需要關(guān)聯(lián)查詢時(shí)再向數(shù)據(jù)庫(kù)發(fā)出sql,以提高數(shù)據(jù)庫(kù)性能。

當(dāng)全部需要關(guān)聯(lián)查詢信息時(shí),此時(shí)不用延遲加載,直接將關(guān)聯(lián)查詢信息全部返回即可,可使用resultType或resultMap完成映射。

查詢緩存 什么是查詢緩存?

mybatis提供查詢緩存,用于減輕數(shù)據(jù)壓力,提高數(shù)據(jù)庫(kù)性能。

mybaits提供一級(jí)緩存,和二級(jí)緩存。

一級(jí)緩存是SqlSession級(jí)別的緩存。在操作數(shù)據(jù)庫(kù)時(shí)需要構(gòu)造 sqlSession對(duì)象,在對(duì)象中有一個(gè)數(shù)據(jù)結(jié)構(gòu)(HashMap)用于存儲(chǔ)緩存數(shù)據(jù)。不同的sqlSession之間的緩存數(shù)據(jù)區(qū)域(HashMap)是互相不影響的。

二級(jí)緩存是mapper級(jí)別的緩存,多個(gè)SqlSession去操作同一個(gè)Mapper的sql語(yǔ)句,多個(gè)SqlSession可以共用二級(jí)緩存,二級(jí)緩存是跨SqlSession的。

為什么要用緩存?

如果緩存中有數(shù)據(jù)就不用從數(shù)據(jù)庫(kù)中獲取,大大提高系統(tǒng)性能。

一級(jí)緩存

工作原理

第一次發(fā)起查詢用戶id為1的用戶信息,先去找緩存中是否有id為1的用戶信息,如果沒(méi)有,從數(shù)據(jù)庫(kù)查詢用戶信息。

得到用戶信息,將用戶信息存儲(chǔ)到一級(jí)緩存中。

如果sqlSession去執(zhí)行commit操作(執(zhí)行插入、更新、刪除),清空SqlSession中的一級(jí)緩存,這樣做的目的為了讓緩存中存儲(chǔ)的是最新的信息,避免臟讀。

第二次發(fā)起查詢用戶id為1的用戶信息,先去找緩存中是否有id為1的用戶信息,緩存中有,直接從緩存中獲取用戶信息。

一級(jí)緩存測(cè)試

Mybatis 默認(rèn)支持一級(jí)緩存,不需要在配置文件中配置。

所以我們直接按照上面的步驟進(jìn)行測(cè)試:

//一級(jí)緩存測(cè)試
    @Test
    public void  testCache1() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //創(chuàng)建UserMapper對(duì)象,mybatis自動(dòng)生成代理對(duì)象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //查詢使用的是同一個(gè)session
        //第一次發(fā)起請(qǐng)求,查詢Id 為1的用戶信息
        User user1 = userMapper.findUserById(1);
        System.out.println(user1);
        //第二次發(fā)起請(qǐng)求,查詢Id 為1的用戶信息
        User user2 = userMapper.findUserById(1);
        System.out.println(user2);
        sqlSession.close();
    }

通過(guò)結(jié)果可以看出第二次沒(méi)有發(fā)出sql查詢請(qǐng)求,

所以我們需要在中間執(zhí)行 commit 操作

//如果sqlSession去執(zhí)行commit操作(執(zhí)行插入、更新、刪除),
// 清空SqlSession中的一級(jí)緩存,這樣做的目的為了讓緩存中存儲(chǔ)的是最新的信息,避免臟讀。
//更新user1的信息,
user1.setUsername("李飛");
//user1.setSex("男");
//user1.setAddress("北京");
userMapper.updateUserById(user1);
//提交事務(wù),才會(huì)去清空緩存
sqlSession.commit();

測(cè)試

一級(jí)緩存應(yīng)用

正式開(kāi)發(fā),是將 mybatis 和 spring 進(jìn)行整合開(kāi)發(fā),事務(wù)控制在 service 中。

一個(gè) service 方法中包括很多 mapper 方法調(diào)用。

service{

     //開(kāi)始執(zhí)行時(shí),開(kāi)啟事務(wù),創(chuàng)建SqlSession對(duì)象

     //第一次調(diào)用mapper的方法findUserById(1)

     //第二次調(diào)用mapper的方法findUserById(1),從一級(jí)緩存中取數(shù)據(jù)

     //方法結(jié)束,sqlSession關(guān)閉

}

如果是執(zhí)行兩次service調(diào)用查詢相同的用戶信息,不走一級(jí)緩存,因?yàn)閟ession方法結(jié)束,sqlSession就關(guān)閉,一級(jí)緩存就清空。

二級(jí)緩存

原理

首先開(kāi)啟mybatis的二級(jí)緩存。

sqlSession1去查詢用戶id為1的用戶信息,查詢到用戶信息會(huì)將查詢數(shù)據(jù)存儲(chǔ)到二級(jí)緩存中。

如果SqlSession3去執(zhí)行相同 mapper下sql,執(zhí)行commit提交,清空該 mapper下的二級(jí)緩存區(qū)域的數(shù)據(jù)。

sqlSession2去查詢用戶id為1的用戶信息,去緩存中找是否存在數(shù)據(jù),如果存在直接從緩存中取出數(shù)據(jù)。

二級(jí)緩存與一級(jí)緩存區(qū)別,二級(jí)緩存的范圍更大,多個(gè)sqlSession可以共享一個(gè)UserMapper的二級(jí)緩存區(qū)域。

UserMapper有一個(gè)二級(jí)緩存區(qū)域(按namespace分) ,其它mapper也有自己的二級(jí)緩存區(qū)域(按namespace分)。

每一個(gè)namespace的mapper都有一個(gè)二緩存區(qū)域,兩個(gè)mapper的namespace如果相同,這兩個(gè)mapper執(zhí)行sql查詢到數(shù)據(jù)將存在相同的二級(jí)緩存區(qū)域中。

開(kāi)啟二級(jí)緩存

mybaits的二級(jí)緩存是mapper范圍級(jí)別,除了在SqlMapConfig.xml設(shè)置二級(jí)緩存的總開(kāi)關(guān),還要在具體的mapper.xml中開(kāi)啟二級(jí)緩存

在 SqlMapConfig.xml 開(kāi)啟二級(jí)開(kāi)關(guān)


然后在你的 Mapper 映射文件中添加一行: ,表示此 mapper 開(kāi)啟二級(jí)緩存。

調(diào)用 pojo 類(lèi)實(shí)現(xiàn)序列化接口

二級(jí)緩存需要查詢結(jié)果映射的pojo對(duì)象實(shí)現(xiàn)java.io.Serializable接口實(shí)現(xiàn)序列化和反序列化操作(因?yàn)槎?jí)緩存數(shù)據(jù)存儲(chǔ)介質(zhì)多種多樣,在內(nèi)存不一樣),注意如果存在父類(lèi)、成員pojo都需要實(shí)現(xiàn)序列化接口。

public class Orders implements Serializable
public class User implements Serializable

測(cè)試

//二級(jí)緩存測(cè)試
    @Test
    public void testCache2() throws Exception
    {
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();


        //創(chuàng)建UserMapper對(duì)象,mybatis自動(dòng)生成代理對(duì)象
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        //sqlSession1 執(zhí)行查詢 寫(xiě)入緩存(第一次查詢請(qǐng)求)
        User user1 = userMapper1.findUserById(1);
        System.out.println(user1);
        sqlSession1.close();


        //sqlSession3  執(zhí)行提交  清空緩存
        UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
        User user3 = userMapper3.findUserById(1);
        user3.setSex("女");
        user3.setAddress("山東濟(jì)南");
        user3.setUsername("崔建");
        userMapper3.updateUserById(user3);
        //提交事務(wù),清空緩存
        sqlSession3.commit();
        sqlSession3.close();
        
        //sqlSession2 執(zhí)行查詢(第二次查詢請(qǐng)求)
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = userMapper2.findUserById(1);
        System.out.println(user2);
        sqlSession2.close();
   }

結(jié)果

useCache 配置

在 statement 中設(shè)置 useCache=false 可以禁用當(dāng)前 select 語(yǔ)句的二級(jí)緩存,即每次查詢都會(huì)發(fā)出sql去查詢,默認(rèn)情況是true,即該sql使用二級(jí)緩存。

    • <ul id="cc4my"><sup id="cc4my"></sup></ul>
      <strike id="cc4my"></strike>
      <abbr id="cc4my"></abbr>
        <ul id="cc4my"><sup id="cc4my"></sup></ul>
        • <