MyBatis中一对多关系的两种处理方法

目录

1.多表联查(通过collection标签的ofType属性)

1)mapper

2)mapper.xml

3)测试代码

4)测试结果

2.分布查询(通过collection标签的select属性)

1)mapper

2)mapper.xml

3)测试代码

4)测试结果

附录

1.Classes实体类

2.student类

3.OneToManyMapper

4.OneToManyMapper.xml

5.OneToManyMapperTest.xml

6.sql

studentSql

classesSql


1.多表联查(通过collection标签的ofType属性)

1)mapper

复制代码
/**
 * collectionBy ofType
 */
Classes queryClassesAndStudentBycollection(@Param("id") int id);

2)mapper.xml

复制代码
<!--collection-->
<resultMap id="collectionResultMap" type="org.xiji.enty.Classes">
    <id property="cid" column="cid"/>
    <result property="className" column="className"/>
    <!--collection-->

    <collection property="students" ofType="org.xiji.enty.Student">
        <id property="sid" column="sid"/>
        <result property="studentName" column="studentName"/>
        <result property="studentAge" column="studentAge"/>
        <result property="classId" column="cid"/>

    </collection>

</resultMap>
<select id="queryClassesAndStudentBycollection" resultMap="collectionResultMap" >

    select * from classes c right join student s on c.cid = s.classId where c.cid=#{id}
</select>

解释:

  1. 主对象映射
    1. MyBatis 使用 resultMap 将查询结果映射到 Classes 对象上。
    2. 主键 cid 和属性 className 直接映射到对应的数据库列。
  2. 集合映射
    1. collection 标签用于映射 Classes 对象中的 students 集合。
    2. 每个 Student 对象的属性 sid, studentName, studentAge, classId 分别映射到对应的数据库列。

3)测试代码

复制代码
/**
 * 通过collection关联查询
 */
@Test
public void queryClassesAndStudentByAssociation()
{
    Classes classes = oneToManyMapper.queryClassesAndStudentBycollection(1);
    System.out.println(classes);
    List<Student> students = classes.getStudents();
    for (Student student : students) {
        System.out.println(student.toString());
    }
}

4)测试结果

2.分布查询(通过collection标签的select属性)

1)mapper

复制代码
/**
 * 分布查询
 */
Classes queryClassesAndStudentByStep(@Param("id") int id);


/**
 * 查询id
 */
List<Student> queryClassesAndStudentByStepTwo(int id);

2)mapper.xml

复制代码
<!--通过分布查询-->
<resultMap id="stepResultMap" type="org.xiji.enty.Classes">
    <id property="cid" column="cid"/>
    <result property="className" column="className"/>
    <collection property="students"
                select="queryClassesAndStudentByStepTwo"
                column="cid"
                ofType="org.xiji.enty.Student"
    >

        <id property="sid" column="sid"></id>
        <result property="classId" column="classId"></result>
        <result property="studentName" column="studentName"></result>
        <result property="studentAge" column="studentAge"></result>
    </collection>

</resultMap>

<select id="queryClassesAndStudentByStep" resultMap="stepResultMap" >
    select *
    from classes where cid=#{id};
</select>

<select id="queryClassesAndStudentByStepTwo" resultType="org.xiji.enty.Student">
    select * from student where classId=#{id}
</select>j

解释:

  1. 主对象映射
    1. MyBatis 使用 resultMap 将查询结果映射到 Classes 对象上。
    2. 主键 cid 和属性 className 直接映射到对应的数据库列。
  2. 分布查询
    1. collection 标签用于映射 Classes 对象中的 students 集合。
    2. 通过 select 属性指定另一个映射语句的 ID,用于执行分布查询。
    3. column 属性指定传递给分布查询的参数列名称,这里是 cid 列。
  3. 子对象映射
    1. 每个 Student 对象的属性 sid, classId, studentName, studentAge 分别映射到对应的数据库列。

3)测试代码

复制代码
/**
 * 通过collection分布查询
 */
@Test
public void queryClassesAndStudentByStep()
{
    Classes classes = oneToManyMapper.queryClassesAndStudentByStep(1);
    System.out.println(classes);
    List<Student> students = classes.getStudents();
    for (Student student : students) {
        System.out.println(student);
    }
}

4)测试结果

附录

1.Classes实体类

java 复制代码
package org.xiji.enty;

import java.util.ArrayList;
import java.util.List;
import org.xiji. enty.Student;

/**
 * 班级表
 */
public class Classes {
    private int cid;
    private String className;


    List<Student> students;


    public List<Student> getStudents() {
        return students;
    }

    public Classes(int id, String className, List<Student> students) {
        this.cid = id;
        this.className = className;
        this.students = students;
    }

    public Classes() {
        students = new ArrayList<>();
    }

    public Classes(int id, String className) {
        this.cid = id;
        this.className = className;
    }

    public int getId() {
        return cid;
    }

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

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }



    public void setStudents(List<Student> students) {
        this.students = students;
    }


    @Override
    public String toString() {
        return "Classes{" +
                "id=" + cid +
                ", className='" + className + '\'' +
                ", students=" + students +
                '}';
    }
}

2.student类

java 复制代码
package org.xiji.enty;
import org.xiji.enty.Classes;

/**
 * 学生表
 */
public class Student {
    private int sid;
    private String studentName;
    private int studentAge;
    private int classId;

   private Classes classes;



    public Student(int id, String studentName, int studentAge, int classId, Classes classes) {
        this.sid = id;
        this.studentName = studentName;
        this.studentAge = studentAge;
        this.classId = classId;
        this.classes = classes;
    }

    public Student(int id, String studentName, int studentAge, int classId) {
        this.sid = id;
        this.studentName = studentName;
        this.studentAge = studentAge;
        this.classId = classId;
    }

    public Student() {

    }

    public int getId() {
        return sid;
    }

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

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public int getStudentAge() {
        return studentAge;
    }

    public void setStudentAge(int studentAge) {
        this.studentAge = studentAge;
    }

    public int getClassId() {
        return classId;
    }

    public void setClassId(int classId) {
        this.classId = classId;
    }

    public Classes getClasses() {
        return classes;
    }

    public void setClasses(Classes classes) {
        this.classes = classes;
    }

    public void setClasses(int id,String className)
    {
        this.classes = new Classes(id,className);
    }
    @Override
    public String toString() {
        return "Student{" +
                "id=" + sid +
                ", studentName='" + studentName + '\'' +
                ", studentAge=" + studentAge +
                ", classId=" + classId +
                ", classes=" + classes +
                '}';
    }
}

3.OneToManyMapper

java 复制代码
package org.xiji.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.xiji.enty.Classes;
import org.xiji.enty.Student;

import java.util.List;

@Mapper
public interface OneToManyMapper {

    /**
     * association
     */
    Classes queryClassesAndStudentByAssociation(@Param("id") int id);

    /**
     * 分布查询
     */
    Classes queryClassesAndStudentByStep(@Param("id") int id);


    /**
     * 查询id
     */
    List<Student> queryClassesAndStudentByStepTwo(int id);


}

4.OneToManyMapper.xml

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="org.xiji.mapper.OneToManyMapper">

    <!--collection-->
    <resultMap id="collectionResultMap" type="org.xiji.enty.Classes">
        <id property="cid" column="cid"/>
        <result property="className" column="className"/>
        <!--collection-->

        <collection property="students" ofType="org.xiji.enty.Student">
            <id property="sid" column="sid"/>
            <result property="studentName" column="studentName"/>
            <result property="studentAge" column="studentAge"/>
            <result property="classId" column="cid"/>

        </collection>

    </resultMap>
    <select id="queryClassesAndStudentByAssociation" resultMap="collectionResultMap" >

        select * from classes c right join student s on c.cid = s.classId where c.cid=#{id}
    </select>


    <!--通过分布查询-->
    <resultMap id="stepResultMap" type="org.xiji.enty.Classes">
        <id property="cid" column="cid"/>
        <result property="className" column="className"/>
        <collection property="students"
                    select="queryClassesAndStudentByStepTwo"
                    column="cid"
                    ofType="org.xiji.enty.Student"
        >

            <id property="sid" column="sid"></id>
            <result property="classId" column="classId"></result>
            <result property="studentName" column="studentName"></result>
            <result property="studentAge" column="studentAge"></result>
        </collection>

    </resultMap>

    <select id="queryClassesAndStudentByStep" resultMap="stepResultMap" >
        select *
        from classes where cid=#{id};
    </select>

    <select id="queryClassesAndStudentByStepTwo" resultType="org.xiji.enty.Student">
        select * from student where classId=#{id}
    </select>




</mapper>

5.OneToManyMapperTest.xml

java 复制代码
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.xiji.enty.Classes;
import org.xiji.enty.Student;
import org.xiji.mapper.ManyToOneMapper;
import org.xiji.mapper.OneToManyMapper;

import java.util.List;

@SpringJUnitConfig(locations = {"classpath:springConfig.xml"})
public class OneTwoManyMapperTest {

    @Autowired
    private OneToManyMapper oneToManyMapper;

    /**
     * 通过collection关联查询
     */
    @Test
    public void queryClassesAndStudentByAssociation()
    {
        Classes classes = oneToManyMapper.queryClassesAndStudentByAssociation(1);
        System.out.println(classes);
        List<Student> students = classes.getStudents();
        for (Student student : students) {
            System.out.println(student.toString());
        }
    }

    /**
     * 通过collection分布查询
     */
    @Test
    public void queryClassesAndStudentByStep()
    {
        Classes classes = oneToManyMapper.queryClassesAndStudentByStep(1);
        System.out.println(classes);
        List<Student> students = classes.getStudents();
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

6.sql

studentSql

sql 复制代码
/*
 Navicat Premium Data Transfer

 Source Server         : mybatis
 Source Server Type    : MySQL
 Source Server Version : 80025
 Source Host           : localhost:3306
 Source Schema         : mybatis

 Target Server Type    : MySQL
 Target Server Version : 80025
 File Encoding         : 65001

 Date: 15/09/2024 23:50:47
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `sid` int NOT NULL AUTO_INCREMENT COMMENT '学生id',
  `studentName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '学生姓名',
  `studentAge` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '学生年龄',
  `classId` int NULL DEFAULT NULL COMMENT '班级id',
  PRIMARY KEY (`sid`) USING BTREE,
  INDEX `classId`(`classId` ASC) USING BTREE,
  CONSTRAINT `classId` FOREIGN KEY (`classId`) REFERENCES `classes` (`cid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, '张三', '18', 1);
INSERT INTO `student` VALUES (2, '李四', '20', 1);
INSERT INTO `student` VALUES (3, '小久', '21', 1);
INSERT INTO `student` VALUES (4, 'xiji', '22', 1);

SET FOREIGN_KEY_CHECKS = 1;

classesSql

sql 复制代码
/*
 Navicat Premium Data Transfer

 Source Server         : mybatis
 Source Server Type    : MySQL
 Source Server Version : 80025
 Source Host           : localhost:3306
 Source Schema         : mybatis

 Target Server Type    : MySQL
 Target Server Version : 80025
 File Encoding         : 65001

 Date: 15/09/2024 23:51:16
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for classes
-- ----------------------------
DROP TABLE IF EXISTS `classes`;
CREATE TABLE `classes`  (
  `cid` int NOT NULL AUTO_INCREMENT COMMENT '班级id',
  `className` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '班级名称',
  PRIMARY KEY (`cid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of classes
-- ----------------------------
INSERT INTO `classes` VALUES (1, '一班');
INSERT INTO `classes` VALUES (2, '二班');
INSERT INTO `classes` VALUES (3, '三班');
INSERT INTO `classes` VALUES (5, '五班');

SET FOREIGN_KEY_CHECKS = 1;
相关推荐
const_qiu7 小时前
第四章 00:开篇 —— 从「会聊天」到「记得住、会干活、能协作」
java·开发语言·人工智能·python
Wang's Blog7 小时前
Java 项目实战: 交友项目 - 个人资料管理的更新接口实现与坑
java·开发语言·交友
团子哒哒7 小时前
数组、切片和Map
后端
Promising_GEO7 小时前
GEE实战02期:从卫星波段开始:利用 Sentinel-2 自己计算 NDVI
java·sentinel·遥感·空间分析
专注仿真8 小时前
ThinkPHP6 API接口开发实例:从零搭建RESTful风格接口
后端·php·restful
大文说跨境8 小时前
亚马逊多账号管理浏览器怎么选?云登/紫鸟/AdsPower 对比
java·前端·自动化
阿里云大数据AI技术8 小时前
StarRocks 与 Fluss 用一条 SQL 查实时与历史
人工智能·sql
开心猴爷8 小时前
应对iOS审核4.3:可以使用 IpaGuard 来给属性名混淆的技术细节与平衡之道
后端·ios
1m555555558 小时前
RAG 工程实战(五):正确知识已经进入 Prompt,为什么大模型还是会答错?
后端·面试
CoderYanger8 小时前
Java EE 进阶:4.Spring Web MVC 入门(第一弹)
java·开发语言·前端·spring·面试·java-ee·mvc