day08-MyBatis的關聯映射02

来源:https://www.cnblogs.com/liyuelian/archive/2023/03/01/17170026.html
-Advertisement-
Play Games

MyBatis的關聯映射02 3.一對多 3.1基本介紹 mybatis – MyBatis 3 | XML 映射器 多對一關係也是一個基本的映射關係,多對一,也可以理解為一對多。例如: User--Pet:一個用戶可以有多只寵物 Dep--Emp:一個部門有多個員工 雙向的多對一關係:通過User ...


MyBatis的關聯映射02

3.一對多

3.1基本介紹

mybatis – MyBatis 3 | XML 映射器

多對一關係也是一個基本的映射關係,多對一,也可以理解為一對多。例如:

User--Pet:一個用戶可以有多只寵物

Dep--Emp:一個部門有多個員工

雙向的多對一關係:通過User可以查詢到對應的所有Pet,反之,通過Pet也可以級聯查詢到對應的User信息。

多對多的關係就是在多對一的關係上拓展

3.2案例實現

映射方式:

方式1:通過配置映射文件實現多對一

方式2:通過註解的方式實現多對一

需求說明:實現級聯查詢,通過user的user_id可以查詢到User信息和關聯的所有pet信息,反之,通過pet的pet_id也可以查詢到Pet信息和user的信息

先創建user表和pet表:

-- 創建user表
CREATE TABLE `user`(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL DEFAULT ''
)CHARSET=utf8
DESC `user`;

-- 創建pet表
CREATE TABLE `pet`(
`id` INT PRIMARY KEY AUTO_INCREMENT,
`nickname` VARCHAR(32) NOT NULL DEFAULT '',
`user_id` INT,
FOREIGN KEY (user_id) REFERENCES `user`(id)
)CHARSET=utf8
image-20230301195756786

3.2.1方式一:配置方式

(1)User和Pet實體類

package com.li.entity;

/**
 * @author 李
 * @version 1.0
 */
public class User {
    private Integer id;
    private String name;
    //因為一個User可以養多個寵物,mybatis使用集合體現這個關係
    private List<Pet> pets;
    
    //setter、getter方法省略
    //雙向映射不要使用toString方法,否則會造成棧溢出錯誤
}
package com.li.entity;

/**
 * @author 李
 * @version 1.0
 */
public class Pet {
    private Integer id;
    private String nickname;
    //一個pet對應一個user對象
    private User user;
    
	//setter、getter方法省略
    //雙向映射不要使用toString方法,否則會造成棧溢出錯誤
}

(2)UserMapper介面和PetMapper介面

public interface UserMapper {
    //通過id獲取User對象
    public User getUserById(Integer id);
}
public interface PetMapper {
    //通過user的id獲取pet對象,可能有多個因此使用集合接收
    public List<Pet> getPetByUserId(Integer userId);
}

(3)UserMapper.xml,思路:

1)先通過user_id查詢得到user信息

2)再根據user_id,查詢對應的pet信息,並映射到user-List< Per> pets

多對多的映射思路和一對一的實現類似,不同的使用使用resultMap映射屬性時使用的是collecting標簽。

<mapper namespace="com.li.mapper.UserMapper">
    <!--通過id獲取User對象
        public User getUserById(Integer id);-->
    <select id="getUserById" parameterType="Integer" resultMap="resultUserMap">
        SELECT * FROM `user` WHERE id = #{id};
    </select>

    <!--User的屬性映射-->
    <resultMap id="resultUserMap" type="User">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <!--1.因為pets屬性是一個集合,因此要使用collection標簽
            2.column="id"的id是SELECT * FROM `user` WHERE id=#{id} 返回的欄位
            3.ofType="Pet"指定返回的集合存放的數據類型-->
        <collection property="pets" column="id" ofType="Pet"
                    select="com.li.mapper.PetMapper.getPetByUserId"/>
    </resultMap>
</mapper>

(4)PetMapper.xml,思路和前面大體相同

<mapper namespace="com.li.mapper.PetMapper">
    <!--通過user的id獲取pet對象,可能有多個因此使用集合接收
        public List<Pet> getPetByUserId(Integer userId);-->
    <select id="getPetByUserId" parameterType="Integer" resultMap="resultPetMap">
        SELECT * FROM `pet` WHERE user_id =#{userId};
    </select>

    <resultMap id="resultPetMap" type="Pet">
        <id property="id" column="id"/>
        <result property="nickname" column="nickname"/>
        <association property="user" column="user_id"
                     select="com.li.mapper.UserMapper.getUserById"/>
    </resultMap>
</mapper>

(5)測試getUserById()方法,通過UserId查找user對象和聯繫的pet信息

@Test
public void getUserById() {
    User user = userMapper.getUserById(2);
    System.out.println("user信息=" + user.getId() + "-" + user.getName());
    for (Pet pet : user.getPets()) {
        System.out.println("寵物信息=" + pet.getId() + "-" + pet.getNickname());
    }
    if (sqlSession != null) {
        sqlSession.close();
    }
}

測試結果:

image-20230301205442816

(6)測試getPetByUserId()方法,通過user的id獲取pet對象

@Test
public void getPetByUserId() {
    List<Pet> pets = petMapper.getPetByUserId(1);
    for (Pet pet : pets) {
        System.out.println("UserId=" + pet.getUser().getId()
                + "-PetId=" + pet.getId()
                + "-PetNickName=" + pet.getNickname());
    }
    if (sqlSession != null) {
        sqlSession.close();
    }
}

測試結果:

image-20230301205827599

resultMap可以復用,如果有其他方法是返回的和resultMap一樣的類型,可以在實現該方法時引用該resultMap。

比如PetMapper介面中新聲明瞭一個方法:

//通過pet的id獲取Pet對象,同時查詢到pet對象關聯的user對象
public Pet getPetById(Integer id);

PerMapper.xml文件:

<!--這裡可以直接復用之前的resultPetMap-->
<select id="getPetById" parameterType="Integer" resultMap="resultPetMap">
    SELECT * FROM `pet` where id =#{id};
</select>

3.2.2方式二:註解方式

需求說明:通過註解的方式,實現雙向的級聯查詢。

在實際開發中推薦使用配置的方式來做

(1)User和Pet實體類不變

(2)直接在介面中,通過註解實現級聯查詢

UserMapperAnnotation.java

package com.li.mapper;

import com.li.entity.User;
import org.apache.ibatis.annotations.*;

/**
 * @author 李
 * @version 1.0
 * 以註解的方式來實現多對一
 */
public interface UserMapperAnnotation {
    //通過id獲取User對象
    @Select(value = "SELECT * FROM `user` WHERE id = #{id}")
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "name", column = "name"),
            //這裡對應返回List類型屬性pets,使用註解的many屬性
            @Result(property = "pets", column = "id",
                    many = @Many(select = 
                                 "com.li.mapper.PetMapperAnnotation.getPetByUserId"))
    })
    public User getUserById(Integer id);
}

PetMapperAnnotation.java

package com.li.mapper;

import com.li.entity.Pet;
import org.apache.ibatis.annotations.*;

import java.util.List;

/**
 * @author 李
 * @version 1.0
 */
public interface PetMapperAnnotation {
    //通過user的id獲取pet對象
    @Select(value = "SELECT * FROM `pet` WHERE user_id =#{userId}")
    //配置了id之後就可以復用PetResuleMap
    @Results(id = "PetResuleMap", value = {
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "nickname", column = "nickname"),
            @Result(property = "user", column = "user_id",
                    one = @One(select = 
                               "com.li.mapper.UserMapperAnnotation.getUserById"))
    })
    public List<Pet> getPetByUserId(Integer userId);

    
    //通過pet的id獲取pet信息
    @Select(value = " SELECT * FROM `pet` where id =#{id}")
    @ResultMap("PetResuleMap")//復用上面的PetResuleMap
    public Pet getPetById(Integer id);
}

3.3練習

自己設計dept(部門)和emp(雇員)表,它們是一對多的關係。

  1. 通過查詢dept,可以級聯查詢到所有的emp信息
  2. 通過查詢emp,也可以級聯查詢到對應的dept信息
  3. 拓展思考:多對多關係

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 情況說明: onKeydown事件觸發條件:容器中某個元素獲取焦點時,按鍵。因此無效的原因是當前容器內並沒有元素獲取焦點。 方案一:容器中監聽快捷鍵 解決方案:利用全局監聽 window.onKeydown document.onkeydown 方案二:視窗中多個容器,監聽各自的快捷鍵 與“方案一” ...
  • 一、https://element-plus.gitee.io/zh-CN/ 官網 二、後臺佈局Layui 代碼示例如下 <template> <div class="app_container"> <div class="common-layout"> <el-container> <el-asi ...
  • 在vue中父子組件傳值是必不可少的,大家必須要學會! 首先父組件向子組件傳值: 父組件:比如我們傳teacher為index,如果我們傳值變數可以使用 : 綁定我們在data中定義的變數。 子組件:為了規範一般使用對象的形式,type表示值的類型,default表示如果不傳值就預設是null. 在子 ...
  • 環境 vue2 導入 安裝npm包 echarts echarts-gl import * as echarts from "echarts" import "echarts-gl" html <div id="map-container"></div> js import GeoZJ from ' ...
  • RxEditor是一款開源企業級可視化低代碼前端,目標是可以編輯所有 HTML 基礎的組件。比如支持 React、VUE、小程式等,目前僅實現了 React 版。 RxEditor運行快照: 項目地址:https://github.com/rxdrag/rxeditor 演示地址( Vercel 部 ...
  • 如何畫好一張架構圖,要做好這件事情首先要回答的就是什麼是架構圖。我們日常工作中經常能看到各種各樣的架構圖,而且經常會發現大家對架構圖的理解各有側重。深入追究到這個問題,可能一下子還很難有一個具象的定義,如果我們把這個問題進行拆分,理解起來就會容易一點。 ...
  • 1. JPA 1.1. 性能直接受底層JDBC驅動性能的影響 1.2. 性能提升是通過改變實體類的位元組碼來實現的 1.2.1. 在類載入到JAR文件或者由JVM運行之前增強位元組碼的方法 1.2.1.1. 在編譯過程中完成的 1.2.1.2. 在實體類編譯完成後,它們會被傳遞給一個特定實現的後置處理器 ...
  • 一、前戲 在之前我們已經學會使用 pytest-html 插件生成 html 格式的測試報告: 1 # 第一步,安裝插件 2 pip install pytest-html 3 ​ 4 # 第二步,執行用例時使用 --html 參數 5 ## main 函數中執行 6 if __name__ == ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...