成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MyBatis的延遲加載,你知道是怎么實現的么?

數據庫 其他數據庫
延遲加載也稱為懶加載、惰性加載,使用延遲加載可以提高程序的運行效率,針對數據持久層的操作,在某些特定查詢的情況下去訪問特定的數據庫,在其他情況下可以不訪問某些數據表,盡量減少 SQL 的執行,從而達到提高速度的目的,是對數據庫操作的一種優化。

今天了不起來說說這個關于 Mybatis ,為什么要說 Mybatis 呢?因為現在面試的時候,除了那些最基礎的,比如如何防止 SQL 注入,以及 Mybatis 的一級緩存,二級緩存之后,還有一些其他的問題,比如 Mybatis 的延遲加載,并且需要說一下延遲加載的使用場景。今天了不起就來給大家說一下這個延遲加載到底是怎么回事,以及延遲加載的使用場景。

什么是延遲加載?

延遲加載也稱為懶加載、惰性加載,使用延遲加載可以提高程序的運行效率,針對數據持久層的操作,在某些特定查詢的情況下去訪問特定的數據庫,在其他情況下可以不訪問某些數據表,盡量減少 SQL 的執行,從而達到提高速度的目的,是對數據庫操作的一種優化。

什么情況下會出現延遲加載的情況

我們來舉個簡單的例子

在一對多中,當我們有一個用戶,它有個100個訂單 在查詢用戶的時候,要不要把關聯的訂單查出來? 在查詢訂單的時候,要不要把關聯的用戶查出來?

那這個時候,答案就很清晰了,肯定要查出來的,但是,是我在需要的地方。

在查詢用戶時,用戶下的訂單應該是,什么時候用,什么時候查詢。

在查詢訂單時,訂單所屬的用戶信息應該是隨著訂單一起查詢出來

這個時候我們就會用到延遲加載了,我用的時候,我們就查詢,我們不用的時候,我們就不再繼續的進行查詢了。

注意:延遲加載的應用要求:關聯對象的查詢與主加載對象的查詢必須是分別進行的select語句,不能是使用多表連接所進行的select查詢。

延遲加載分類

其實延遲加載也是有區分對的,而這個區分就是,全局的延遲加載和局部的延遲加載。

全局延遲加載

全局延遲加載的實現,實際上是通過修改配置文件來進行實現的,只要改了對應的配置配置文件,重啟之后,肯定直接全局實現,所有需要用到全局加載的 xml 文件,都可以進行實現了。

修改內容如下:

<settings>
    <!--開啟全局延遲加載功能-->
    <setting name="lazyLoadingEnabled" value="true"/>
</settings>

局部延遲加載

在association和collection標簽中都有?個fetchType屬性,通過修改它的值,可以修改局部的加載策略。

實現方式如下:

<!-- 開啟?對多 延遲加載 -->
<resultMap id="userMap" type="user">
    <id column="id" property="id"></id>
    <result column="username" property="username"></result>
    <result column="password" property="password"></result>
    <result column="birthday" property="birthday"></result>
<!--
fetchType="lazy" 懶加載策略
fetchType="eager" ?即加載策略
-->
    <collection property="orderList" ofType="order" column="id"
        select="com.lagou.dao.OrderMapper.findByUid" fetchType="lazy">
    </collection>
</resultMap>
<select id="findAll" resultMap="userMap">
    SELECT * FROM `user`
</select>

其實在這里,我們需要注意一個內容,那就是延遲加載的時候:局部的加載策略的優先級高于全局的加載策略。

這個也是面試的時候,經常會被問到的內容。

那么我們就得來看看這個延遲加載的具體實現:

Spring配置加載

public class Configuration {
        /**
         * aggressiveLazyLoading:
         * 當開啟時,任何?法的調?都會加載該對象的所有屬性。否則,每個屬性會按需加載(參考lazyLoadTriggerMethods).
         * 默認為true
         */
        protected boolean aggressiveLazyLoading;
        /**
         * 延遲加載觸發?法
         */
        protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[]{"equals", "clone", "hashCode", "toString" }));
        /**
         * 是否開啟延遲加載
         */
        protected boolean lazyLoadingEnabled = false;
 
        /**
         * 默認使?Javassist代理??
         *
         * @param proxyFactory
         */
        public void setProxyFactory(ProxyFactory proxyFactory) {
            if (proxyFactory == null) {
                proxyFactory = new JavassistProxyFactory();
            }
            this.proxyFactory = proxyFactory;
        }
        //省略...
    }

Spring的加載,我們已經看到了,接下來我們還得看看延遲加載代理對象創建,他都是怎么來創建的,說到創建類,那么就得找到這個 ResultSetHandler 這個類了,內部是有有個 handleResultSets 的方法,而方法內部,就有加載的過程。默認采用javassistProxy進行代理對象的創建

// 創建映射后的結果對象
    private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
        // useConstructorMappings ,表示是否使用構造方法創建該結果對象。此處將其重置
        this.useConstructorMappings = false; // reset previous mapping result
        final List<Class<?>> constructorArgTypes = new ArrayList<>(); // 記錄使用的構造方法的參數類型的數組
        final List<Object> constructorArgs = new ArrayList<>(); // 記錄使用的構造方法的參數值的數組
        // 創建映射后的結果對象
        Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);
        if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
            // 如果有內嵌的查詢,并且開啟延遲加載,則創建結果對象的代理對象
            final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
            for (ResultMapping propertyMapping : propertyMappings) {
                // issue gcode #109 && issue #149
                if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {
               // 創建延遲加載代理對象
                    resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
                    break;
                }
            }
        }
        // 判斷是否使用構造方法創建該結果對象
        this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping result
        return resultObject;
    }

如果你想要在你的代碼中驗證延遲加載是否生效的話,那么有一個很簡單的方法,開啟日志的 SQL 打印功能,那么就可以直接驗證你的延遲加載是否生效了。

為什么需要延遲加載

其實這也是延遲加載的優點,優點如下:

先從單表查詢,需要時再從關聯表去關聯查詢,??提?數據庫性能,因為查詢單表要比關聯查詢多張表速度要快。

但是缺點也很明顯:

有當需要用到數據時,才會進行數據庫查詢,這樣在大批量數據查詢時,因為查詢工作也要消耗時間,所以可能造成?戶等待時間變長,造成用戶體驗下降。

責任編輯:武曉燕 來源: Java極客技術
相關推薦

2021-01-21 09:09:18

時區轉換程序

2024-11-26 00:45:29

free區域字段

2023-08-30 07:27:39

2020-10-16 15:06:59

開發技術方案

2025-01-21 10:04:40

Java并發阻塞隊列

2024-04-10 10:15:16

監聽

2024-12-04 08:40:19

2013-02-27 10:27:44

GitHub

2024-02-19 00:00:00

Docker輕量級容器

2024-02-22 09:21:09

.NETActionOptions

2020-06-29 18:54:39

大數據新發地疫情

2010-01-06 15:36:30

Linux操作系統

2023-10-08 09:42:41

GitHubDataTable?Fill

2022-12-09 09:46:55

插件Lombok

2022-08-11 17:14:37

Java

2021-01-13 10:56:37

MybatisAPIMybatis 架構

2017-12-11 15:04:58

404錯誤HTTP代碼

2020-12-08 09:25:41

死鎖MySQL數據庫

2024-12-11 08:19:34

2020-12-17 08:56:51

單例模式JVM
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产原创在线观看 | 久草视频在线播放 | 日本字幕在线观看 | 亚洲va欧美va天堂v国产综合 | 色吊丝在线 | 亚洲精品粉嫩美女一区 | 日韩综合一区 | 亚洲人成人一区二区在线观看 | 美女天堂av| 欧美视频第二页 | 日日操夜夜操天天操 | 一区二区三区四区电影视频在线观看 | 在线一级片 | 欧美999 | 成年人网站国产 | 黑人精品欧美一区二区蜜桃 | 亚洲精品乱码久久久久v最新版 | 色综合网站 | 国产精品欧美一区喷水 | 欧洲妇女成人淫片aaa视频 | 久久9精品 | 欧美激情啪啪 | 一区二区三区电影在线观看 | 91夜夜夜| 91亚洲精品在线 | 91精品国产91综合久久蜜臀 | 日本亚洲欧美 | www久久爱 | 亚洲精品自在在线观看 | 99精品99久久久久久宅男 | 日本精品一区二区三区在线观看视频 | 91久久精品日日躁夜夜躁国产 | 不卡一区二区在线观看 | 日韩欧美国产一区二区 | 狠狠操狠狠操 | 久久中文字幕在线 | 浮生影院免费观看中文版 | 亚洲久视频 | 拍真实国产伦偷精品 | 国产精品亚洲片在线播放 | 日本不卡免费新一二三区 |