MyBatis(十六):多對一的處理

来源:https://www.cnblogs.com/jmsstudy/archive/2022/09/15/16696878.html
-Advertisement-
Play Games

現在我們就開始更加深入的學習了,今天我們要學習的是多對一的處理。 在正式開始之前我們需要做一些準備工作。 一、在資料庫建立兩張新的表並插入數據 CREATE TABLE `teacher` ( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NUL ...


現在我們就開始更加深入的學習了,今天我們要學習的是多對一的處理。

在正式開始之前我們需要做一些準備工作。

一、在資料庫建立兩張新的表並插入數據

CREATE TABLE `teacher` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  PRIMARY KEY(`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO `teacher`(`id`, `name`) VALUES (1, '劉老師');

CREATE TABLE `student` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO `student` (`id`,`name`,`tid`) VALUES (1,'小趙','1');
INSERT INTO `student` (`id`,`name`,`tid`) VALUES (2,'小錢','1');
INSERT INTO `student` (`id`,`name`,`tid`) VALUES (3,'小孫','1');
INSERT INTO `student` (`id`,`name`,`tid`) VALUES (4,'小李','1');
INSERT INTO `student` (`id`,`name`,`tid`) VALUES (5,'小周','1');

上述SQL語句建立了一個teacher表,一個student表,student表的tid與teacher表的id相關聯。

二、建立一個新的項目

我們建立一個全新的子項目

1.建立MyBatis的核心配置文件mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <properties resource="db.properties" />

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    
    <typeAliases>
        <package name="com.jms.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

2.建立db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/MyBaties?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456

3.建立MyBatisUtil工具類

package com.jms.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

//SqlSessionFactory-->SqlSession
public class MyBatisUtil {

    private static SqlSessionFactory sqlSessionFactory;

    //獲取SqlSessionFactory對象
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //通過SqlSessionFactory獲取SqlSession對象,其中包含了面向資料庫執行執行SQL命令所需要的方法
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession(true);
    }
}

4.建立實體類

Student

package com.jms.pojo;

public class Student {
    private int id;
    private String name;
    private Teacher teacher;

    public Student() {
    }

    public Student(int id, String name, Teacher teacher) {
        this.id = id;
        this.name = name;
        this.teacher = teacher;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", teacher=" + teacher +
                '}';
    }
}

Teacher

package com.jms.pojo;

public class Teacher {
    private int id;
    private String name;

    public Teacher(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Teacher() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

5.建立Mapper介面

StudentMapper

TeacherMapper

6.建立Mapper.xml配置文件

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jms.dao.StudentMapper">

</mapper>

TeacherMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jms.dao.TeacherMapper">

</mapper>

6.在核心配置文件mybatis-config.xml中建立映射

    <mappers>
        <mapper resource="com/jms/dao/TeacherMapper.xml"/>
        <mapper resource="com/jms/dao/StudentMapper.xml"/>
    </mappers>

 7.測試

(1)在介面中寫一個方法

package com.jms.dao;

import com.jms.pojo.Teacher;
import org.apache.ibatis.annotations.Select;

import java.util.List;

public interface TeacherMapper {

    List<Teacher> getTeacherList();
}

(2)在Mapper.xml文件中實現

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 命名空間namespace對應Mapper介面 -->
<mapper namespace="com.jms.dao.TeacherMapper">
    <select id="getTeacherList" resultType="teacher">
        select * from mybaties.teacher
    </select>
</mapper>

(3)junit測試

import com.jms.dao.TeacherMapper;
import com.jms.pojo.Teacher;
import com.jms.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class MapperTest {
    @Test
    public void test() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class);
        List<Teacher> teacherList = teacherMapper.getTeacherList();
        for (Teacher teacher : teacherList) {
            System.out.println(teacher);
        }
    }
}

 

 

測試結果沒有問題。

至此,我們的資料庫和項目都搭建完成。

接下來就進行多對一處理的實現。

三、多對一處理的實現

首先我們要清楚我們要做什麼?

我們要查詢所有的student信息。查詢所有student信息不是很簡單嗎?一般來說確實很簡答,但是我們Student類中有一個屬性是Teacher對象。Teacher對象還有著自己的id和name。所以我們要查的是student表中的id和name,以及它們的tid所對應的teacher表中的id和name。

我們先利用SQL來查詢看看。

select s.id,s.name,t.id,t.name
from student as s,teacher as t
where s.tid = t.id

上表即我們想要得到的結構。

那麼在MyBatis中我們如何去實現呢?

我們有兩種方法。

1.按照結果嵌套處理

顧名思義,就是先通過查詢得到結果,把結果中的四個列對應給Student類的三個屬性,最後兩列對應給Teacher對象的兩個屬性。

由於student表和teacher中的id欄位和name欄位名字相同,所以我們在MyBatis中查詢的時候應該給它起別名(不同的話就沒有必要了)。

(1)在StudentMapper介面中聲明方法

package com.jms.dao;

import com.jms.pojo.Student;

import java.util.List;

public interface StudentMapper {

    List<Student> getStudentList();
}

(2)在StudentMapper.xml中實現介面中的方法

    <!--按照結果嵌套處理-->
    <resultMap id="StudentAndTeacher" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <!--複雜的屬性要單獨處理-->
        <association property="teacher" javaType="Teacher">
            <result property="id" column="tid"/>
            <result property="name" column="tname"/>
        </association>
    </resultMap>

    <select id="getStudentList" resultMap="StudentAndTeacher">
        select s.id as sid,s.name as sname,t.id as tid,t.name as tname
        from mybaties.student as s,mybaties.teacher as t
        where s.tid = t.id
    </select>

我們看上面的配置,還是常規的select語句和結果映射,唯一有變化的就是結果映射中多了一個對於複雜屬性的處理。

官方文檔中是這樣說明的:

association – 一個複雜類型的關聯;許多結果將包裝成這種類型

  嵌套結果映射 – 關聯可以是 resultMap 元素,或是對其它結果映射的引用

javaType 一個 Java 類的全限定名,或一個類型別名(關於內置的類型別名,可以參考上面的表格)。 如果你映射到一個 JavaBean,MyBatis 通常可以推斷類型。然而,如果你映射到的是 HashMap,那麼你應該明確地指定 javaType 來保證行為與期望的相一致。

(3)junit測試

import com.jms.dao.StudentMapper;
import com.jms.dao.TeacherMapper;
import com.jms.pojo.Student;
import com.jms.pojo.Teacher;
import com.jms.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class MapperTest {

    @Test
    public void getStudents() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> studentList = studentMapper.getStudentList();
        for (Student student : studentList) {
            System.out.println(student);
        }
    }
}

測試結果如下:

 成功得到了想要的結果。

2.按照查詢進行嵌套處理

顧名思義,就是查詢中嵌套著查詢。這個我們要實現,很明顯我們需要先對student表進行查詢,將結果中的tid作為第二個查詢的條件來查詢teacher表。

(1)在StudentMapper介面聲明方法

List<Student> getStudentList2();

(2)在StudentMapper.xml中實現介面中的方法

    <resultMap id="StudentAndTeacher2" type="Student">
        <!--此處的id和name的映射是可以省略的,寫出來只是為了方便理解-->
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>

    <select id="getStudentList2" resultMap="StudentAndTeacher2">
        select * from mybaties.student
    </select>

    <select id="getTeacher" resultType="Teacher">
        select * from mybaties.teacher where id=#{tid}
    </select>

上面的id和name在隱性映射中已經存在,可以不寫這兩句,寫出來是為了方便理解。

這種方法相比第一種可能難理解一些,但也不是很難。將tid列與teacher屬性進行對應,然後嵌套一個查詢,這個查詢返回的是一個Teacher類型,剛好把查詢結果返給對應的teacher屬性。

這裡令我感到意外的是select的id,竟然還能作為被引用的對象,於是我看了一下官方文檔的內容:

Select 元素的屬性
屬性描述
id

在命名空間中唯一的標識符,可以被用來引用這條語句。

select的id在命名空間的標識符就是說去介面中找方法名,同樣說到可以被引用,嗯,學習了。

(3)junit測試

 

 同樣得到了結果。

 

(本文僅作個人學習記錄用,如有紕漏敬請指正)

 


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

-Advertisement-
Play Games
更多相關文章
  • 我的設計模式之旅,本文是對《大話設計模式》基礎知識的補充。原書部分概念沒有說清楚,如里氏替換原則的幾點要求,三大類設計模式各個概念等等,為補充相關知識我閱讀了《深入設計模式》,於是有了這篇前置文章。方便入門程式員瞭解更多基礎知識。 ...
  • 安全是產品的底座,是體驗的基礎,也是企業的一項核心競爭力。安全生產是一項系統性的工作,同時也是一件比較瑣碎的事,需要做方方面面的考慮盡一切可能保障系統安全穩定運行。個人之前一直負責商品的穩定性工作,在這方面有比較多的經歷和實踐。 記得在18年的時候,我們做商品發佈的組件化改造,當時正好碰上網站剛開... ...
  • 我的設計模式之旅,使用 Golang 實現。本節實現策略模式與簡單工廠。編程旅途是漫長遙遠的,在不同時刻有不同的感悟,本文會一直更新下去。 ...
  • 有時候,我們明明在類或者方法上添加了@Transactional註解,卻發現方法並沒有按事務處理。其實,以下場景會導致Spring的@Transactional事務失效。 1、事務方法所在的類沒有載入到Spring IOC容器中。 @Transactional是Spring的註解,未被Spring管 ...
  • 個人博客:槿蘇的知識鋪 一、什麼是自動裝配 SpringBoot 定義了一套介面規範,這套規範規定:SpringBoot在啟動時會掃描外部引用jar包中的META-INF/spring.factories文件,將文件中配置的類型信息載入到Spring容器,並執行類中定義的各種操作。對於外部jar包來 ...
  • 真是一本透著編程思想的書。 上面的書讓你從微觀角度瞭解 Java,而這本書則可以讓你從一個巨集觀角度瞭解 Java。 這本書和 Java 核心技術的厚度差不多,但這本書的信息密度比較大。 所以,讀起來是非常耗大腦的,因為它會讓你不斷地思考。 對於想學好 Java 的程式員來說,這是一本必讀的書。 -... ...
  • 上一篇我們學習了多對一的處理,這次我們來學習一對多的處理。 一對多的處理與多對一的處理差別不大,只是有一些細微的地方需要註意。 我們還是先做準備工作,其他部分與多對一的準備工作相同,僅實體類構建需要做出改變。 一、修改實體類 Student類: package com.jms.pojo; publi ...
  • 前因後果 公司新來的小姐姐,超級喜歡看漫畫,天天給我介紹,好煩~ 現在是2022年9月15日16點30,於是我決定, 五點下班前寫個代碼把她說的漫畫全部爬下來,應付一下~ 再發篇文章揭露她的罪惡,嘿嘿~ 準備事項 環境使用 Python 3.8 Pycharm 2021.2版本 模塊使用 impor ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...