Mybatis高級查詢之一對一查詢的四種方法(筆記)

1. 一對一查詢

1.1-1.3 我們假設場景爲用戶和角色一對一,根據數據庫基本原理,我們把外鍵設置在用戶一邊,即在實體類中添加角色這個屬性。

1.1 一對一嵌套結果查詢

1.1.1嵌套結果查詢的核心思想

  • 核心思想:直接用slect標籤通過數據庫字段和實體類字段的自動映射。
    • 首先在select語句中指明映射關係。
    • 然後我們看resultType的值是一個實體類。
    • 自動映射到實體類。
  • 應用在場景中:我們假設用戶和角色之間是一對一,在用戶類中一個屬性是角色 sysrole類型的,查詢用戶的時候把所歸屬的角色查詢出來,那麼其就可以寫成如圖所示。
    • user_name userName代表數據庫字段和實體類中字段
    • r.id "role.id"此處是通過別名映射的,role是什麼?是聲明在user類中屬性。
      enter description here

1.1.2 嵌套結果查詢優缺點

  1. 什麼是?通過了一次查詢把結果映射到了不同對象裏。
  2. 好處是什麼?減少了數據庫查詢次數,減少了數據庫的壓力。
  3. 壞處是什麼?要寫複雜的SQL,不容易寫對,由於要映射到不同的對象中,一定程度上增加了服務器的壓力。

1.2 使用resultMap配置一對一映射

1.2.1 具體應用過程

我們在1.1中使用的方法是直接在select標籤中直接寫後自動映射到實體類,resultType返回類型是一個實體類。還有一種方法是在xml文件中的標籤配置關係,然後再在select的resultType指定返回resultMap。詳細如圖所示:
enter description here
property是實體類字段名,colum是數據庫字段名。此處resultMap這個標籤是定義了一種映射關係集合,這個集合的類型對應實體類User,所以type指定了一個實體類。同樣我們在property中仍可以使用別名.字段的方法,同1.1。
那麼我們來看,select語句是怎麼寫的。
enter description here

1.2.2 注意事項

注意的是:去掉了數據庫字段,直接用實體類屬性查詢。至於那個別名問題,暫時還沒有想到會出現的場景,只需記住若是使用別名別名和resultMap的column一致

1.2.3 簡化寫法

首先我們看這張圖
enter description here
在實際的場景中我們一般會單獨爲user寫一個映射文件(這個映射文件通常是自動生成工具生成的)裏面,resultMap會寫成如圖所示。這時候,我們要加一個嵌套查詢的方法,那麼resultMap需要添加一個?這時候我們要在寫一個,如1.2.1圖,我們會發現有好多重複的內容。如下圖所示。
enter description here
這個時候,我們引入一種**繼承(增加extend屬性)**機制。改成如下圖所示。
enter description here

1.3 使用resultMap的association標籤配置一對一映射

enter description here

  • 在這裏我們使用了association那麼property中就直接寫屬性名就可以。
  • 這裏我們配置了列的前綴,則在Column就可以省略,但是select就要更改如下。
    enter description here
  • 關於associationresultMap屬性應用場景
    我們可以把角色的關聯單獨拿出來。
    enter description here
    把這部分單獨放到一個resultMap標籤中,然後直接代用即可。
    enter description here
    • 注意事項
    • 同xml可以使用ID,不在同一xml用全類名+ID如上圖。

1.4 association標籤查詢(懶加載)

此處我們假設場景是新的,用戶和博客存在一對一關係,按照數據庫設計的基本原理,我們再user中設置外鍵指向blog表,對應實體類就是user類中增加Blog類型的blog屬性。

1.4.1 與前1.1-1.3三種方式的區別

  • 前三種方式都是複雜查詢
  • 前三種方式都是一次性複雜查詢,映射到不同的對象中。
  • 此種方法可以理解爲簡單查詢,後再根據業務邏輯手動查詢關聯對象,所以出現了急速加載和懶加載的概念。

1.4.2 具體實例

enter description here
enter description here
association中的屬性介紹

  • select:從查詢ID
  • column:從查詢入參=主查詢字段名,見圖。可以包含多個用{查詢入參=主查詢字段名,…}
  • fetchType:數據加載方式

查詢語句執行順序

  • 執行主查詢->執行從查詢
  • 先查出用戶,然後根據用戶中的blogId去執行從查詢,依次輪流有多少用戶查多少次主查詢->從查詢,主查詢->從查詢,主查詢->從查詢,主查詢->從查詢…

存在問題

  • 如果我們查出來從查詢的數據,即博客,這個數據並沒有用呢?
  • 如果我們用戶查詢主查詢用戶有N個,則需要執行N次查詢,每次主查詢會再查詢依次從查詢,則會出現N+1的問題。(其實就是eager加載問題對比JPA)

解決方法

  • 增加fetchtype屬性設定爲eager,這樣只有我們在getBlog()方法纔會執行從查詢。
    enter description here
    我們觀察運行結果,會出現從查詢依舊會被執行,而不是再調用getBlog方法才執行。
    原因及解決方法 :在mybatis全局配置中有一個屬性aggressive-lazy-loading: false,這個參數默認爲true,即如果爲true,不管你是否設置lazy都會全部加載。
    enter description here
  • 懶加載注意事項
    enter description here
  • 當我們設置好aggressive-lazy-loading: false,我們如果想進行從查詢呢?
    enter description here
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章