MybatisPlus二级映射和关联对象ResultMap

文章目录

  • 一、业务背景
      • 1. 数据库表结构
      • 2. 需求
  • 二、使用映射直接得到指定结构
  • 三、其他文件
      • 1. Mapper
      • 2. Service
      • 3. Controller
  • 四、概念理解
      • 一级映射
      • 二级映射
      • 聚合
  • 五、标签使用
      • 1. \ 标签
      • 2. \ 标签

在我们的教程中,我们设计了一个课程内容的数据结构,包含章节和相关资源。这种结构非常适合在线教育平台或电子学习系统,其中课程内容需要被组织成不同的章节和子章节,每个子章节可能关联特定的学习资源。

这将是一个很好的示例来展示 MyBatis 中如何使用一对多()和一对一()映射。

一、业务背景

1. 数据库表结构

  1. 章节表 (chapter)
    这张表包含所有章节的信息,其中包括大章节和小章节。大章节作为容器,可以包含多个小章节。
    • id (章节ID)
    • parent_id (父章节ID,用于区分大章节和小章节)
    • name (章节名称)
    • courseId (课程ID)
public class Chapter {
    private Long id;
    private Long parentId;
    private String name;
    private Long courseId;
}
  1. 资源表 (resource)
    这张表包含与小章节相关联的资源信息。
    • id (资源ID)
    • section_id (章节ID,关联到章节表)
    • name (资源名称)
public class Resource {
    private Long id;
    private Long sectionId;
    private String name;
}

2. 需求

要求根据courseId查询出指定课程的信息,包括大章节、小章节、资源,并以一定结构返回,比如

[
    {
        "id": 1,
        "parentId": null,
        "name": "Chapter 1",
        "courseId": 100,
        "subChapters": [
            {
                "id": 11,
                "parentId": 1,
                "name": "Section 1.1",
                "courseId": 100,
                "resource": {
                    "id": 101,
                    "sectionId": 11,
                    "name": "Introduction Video"
                }
            },
            {
                "id": 12,
                "parentId": 1,
                "name": "Section 1.2",
                "courseId": 100,
                "resource": null
            }
        ],
        "resource": null
    }
    // other...
]

所以我们定义一个Dto如下

public class ChapterDto extends Chapter {
    private List<ChapterDto> subChapters;
    private Resource resource;

    // 构造器、getter和setter
}

二、使用映射直接得到指定结构

ChapterMapper.xml 文件中,我们定义 SQL 查询以及结果映射。

<mapper namespace="com.example.mapper.ChapterMapper">

    <resultMap id="ChapterDtoMap" type="com.example.dto.ChapterDto">
        <id column="chapter_id" property="id" />
        <result column="parent_id" property="parentId" />
        <result column="name" property="name" />
        <result column="courseId" property="courseId" />
        <collection property="subChapters" ofType="com.example.dto.ChapterDto">
            <id column="sub_chapter_id" property="id" />
            <result column="sub_parent_id" property="parentId" />
            <result column="sub_name" property="name" />
            <result column="sub_courseId" property="courseId" />
            <association property="resource" javaType="com.example.model.Resource">
                <id column="resource_id" property="id" />
                <result column="section_id" property="sectionId" />
                <result column="resource_name" property="name" />
            association>
        collection>
    resultMap>

    <select id="selectChaptersWithResources" resultMap="ChapterDtoMap">
        SELECT
            c.id AS chapter_id, c.parent_id, c.name, c.courseId,
            sc.id AS sub_chapter_id, sc.parent_id AS sub_parent_id, sc.name AS sub_name, sc.courseId AS sub_courseId,
            r.id AS resource_id, r.section_id, r.name AS resource_name
        FROM
            chapter c
        LEFT JOIN
            chapter sc ON c.id = sc.parent_id
        LEFT JOIN
            resource r ON sc.id = r.section_id
        WHERE
            c.courseId = #{courseId} AND c.parent_id IS NULL
    select>

mapper>

三、其他文件

1. Mapper

public interface ChapterMapper {
    List<ChapterDto> selectChaptersWithResources(Long courseId);
}

2. Service

@Service
public class ChapterService {
    @Autowired
    private ChapterMapper chapterMapper;

    public List<ChapterDto> getChaptersWithResources(Long courseId) {
        return chapterMapper.selectChaptersWithResources(courseId);
    }
}

3. Controller

@RestController
@RequestMapping("/chapters")
public class ChapterController {
    @Autowired
    private ChapterService chapterService;

    @GetMapping("/{courseId}")
    public ResponseEntity<List<ChapterDto>> getChapters(@PathVariable Long courseId) {
        List<ChapterDto> chapters = chapterService.getChaptersWithResources(courseId);
        return ResponseEntity.ok(chapters);
    }
}

四、概念理解

一级映射

在提供的 resultMap 中,一级映射是针对 ChapterDto类的直接属性的映射。这意味着数据库中的列(如 chapter_id, parent_id等)直接映射到 ChapterDto类的相应属性(如 id, parent_id等),这部分映射是非常直接的。

二级映射

二级映射用于处理复杂的对象关系,比如当一个对象包含其他对象或对象的集合时。这通常在处理一对多关系时出现,例如,一个章节结构(ChapterDto)可能包含多个子章节。

聚合

这种聚合是根据您在 标签中定义的规则进行的。MyBatis 会识别哪些行应该被映射为独立的实例,哪些行应该作为子元素聚合到其他实例中。

五、标签使用

1. 标签

用途:用于映射一对多关系。在这个例子中,ChapterDto类包含一个 Chapter 类型的列表,这代表了大章节和小章节之间的一对多关系。

常用属性

  • property:指定要映射到的目标属性名称。
  • ofType:指定集合中元素的类型。

2. 标签

用途:用于映射一对一关系。在您的例子中,ChapterDto包含一个 Resource 类型的属性,这代表了小章节和资源之间的一对一关系。
常用属性

  • property:指定要映射到的目标属性名称。
  • javaType:指定关联对象的类型。

MybatisPlus二级映射和关联对象ResultMap_第1张图片

你可能感兴趣的:(SpringBoot3,#,MyBatisPlus,java,mybatis,spring,boot)