【Mybatis3】—— 使用collection处理一对多映射

1. 创建数据库表

tb_classroom 帖子表

-- Table: public.tb_classroom

-- DROP TABLE public.tb_classroom;

CREATE TABLE public.tb_classroom
(
    id integer NOT NULL DEFAULT nextval('tb_classroom_id_seq'::regclass),
    classroom_no character varying(20) COLLATE pg_catalog."default" NOT NULL,
    name character varying(20) COLLATE pg_catalog."default" NOT NULL,
    CONSTRAINT tb_classroom_pkey PRIMARY KEY (id)
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

ALTER TABLE public.tb_classroom
    OWNER to postgres;
COMMENT ON TABLE public.tb_classroom
    IS '班级信息表';

-- Index: unique_index_on_classroom_no

-- DROP INDEX public.unique_index_on_classroom_no;

CREATE UNIQUE INDEX unique_index_on_classroom_no
    ON public.tb_classroom USING btree
    (classroom_no COLLATE pg_catalog."default")
    TABLESPACE pg_default;

插入数据:

INSERT INTO "public"."tb_classroom" VALUES ('1', 'C003001', '三年一班');
INSERT INTO "public"."tb_classroom" VALUES ('3', 'C003002', '三年二班');

tb_student 用户表

-- Table: public.tb_student

-- DROP TABLE public.tb_student;

CREATE TABLE public.tb_student
(
    id integer NOT NULL DEFAULT nextval('tb_student_id_seq'::regclass),
    student_no character varying(20) COLLATE pg_catalog."default" NOT NULL,
    name character varying(20) COLLATE pg_catalog."default" NOT NULL,
    age smallint NOT NULL,
    score real NOT NULL,
    classroom_no character varying(20) COLLATE pg_catalog."default" NOT NULL,
    CONSTRAINT tb_student_pkey PRIMARY KEY (id)
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

ALTER TABLE public.tb_student
    OWNER to postgres;
COMMENT ON TABLE public.tb_student
    IS '学生信息表';

-- Index: unique_index_on_student_no

-- DROP INDEX public.unique_index_on_student_no;

CREATE UNIQUE INDEX unique_index_on_student_no
    ON public.tb_student USING btree
    (student_no COLLATE pg_catalog."default")
    TABLESPACE pg_default;

插入数据:

INSERT INTO "public"."tb_student" VALUES ('1', 'S315060012', '小明', '25', '88.5', 'C003001');
INSERT INTO "public"."tb_student" VALUES ('2', 'S315060039', '小黄', '24', '92.5', 'C003001');
INSERT INTO "public"."tb_student" VALUES ('3', 'S315060011', '小白', '22', '85', 'C003002');

2. 创建POJO对象

Classroom 对象

package com.tao.springmybatispostgresql.entity;

import lombok.*;

import java.util.List;

/**
 * 班级实体, 对应数据库中的tb_classroom表
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Classroom {

    private Integer id;
    private String classroomNo;
    private String name;

    /**
     * 注意: 我们在Classroom类中定义一个studentList,
     * 用来表示在同一个班的所有学生的集合.
     * 这里虽然在tb_classroom表中没有对应的字段, 但是也是可以这样定义的.
     */
    private List<Student> studentList;
}

Student 对象

package com.tao.springmybatispostgresql.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 学生实体, 对应数据库中的tb_student表
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {

    private Integer id;
    private String studentNo;
    private String name;
    private Integer age;
    private Float score;
    private String classroomNo;
}

3. 创建接口和xml文件

IClassroomMapper 接口

package com.tao.springmybatispostgresql.mapper;

import com.tao.springmybatispostgresql.entity.Classroom;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

/**
 * 班级实体对应的数据操作接口
 */
@Mapper
@Repository("classroomMapper")
public interface IClassroomMapper {

    /**
     * 通过classroomNo获取对应Classroom对象的信息
     * @param classroomNo
     * @return
     */
        Classroom getClassroomByNo(String classroomNo);
}

ClassroomMapper.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.tao.springmybatispostgresql.mapper.IClassroomMapper">

    <resultMap id="classroomResultMap" type="com.tao.springmybatispostgresql.entity.Classroom">
        <id property="id" column="c_id"/>
        <result property="classroomNo" column="classroom_no"/>
        <result property="name" column="classroom_name"/>

        <collection property="studentList" ofType="com.tao.springmybatispostgresql.entity.Student">
            <id property="id" column="s_id"/>
            <result property="studentNo" column="student_no"/>
            <result property="name" column="student_name"/>
            <result property="age" column="age"/>
            <result property="score" column="score"/>
            <result property="classroomNo" column="classroom_no"/>
        </collection>
    </resultMap>


    <select id="getClassroomByNo" parameterType="String" resultMap="classroomResultMap">
        SELECT
            c.id AS c_id,
            c.classroom_no,
            c.name AS classroom_name,
            s.id AS s_id,
            s.student_no,
            s.name AS student_name,
            s.age,
            s.score,
            s.classroom_no
        FROM tb_classroom c, tb_student s
        WHERE s.classroom_no = c.classroom_no AND c.classroom_no = #{classroomNo}
    </select>

</mapper>

4. Controller 测试

package com.tao.springmybatispostgresql.web.controller;

import com.tao.springmybatispostgresql.entity.Classroom;
import com.tao.springmybatispostgresql.entity.Post;
import com.tao.springmybatispostgresql.mapper.IClassroomMapper;
import com.tao.springmybatispostgresql.mapper.IPostMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    IClassroomMapper classroomMapper;

    @GetMapping("/classroom/get/{classroomNo}")
    public Classroom getClassroomInfoByClassroomNo(@PathVariable("classroomNo") String classroomNo) {

        Classroom classroom = classroomMapper.getClassroomByNo(classroomNo);
        return classroom;
    }
}

5. 结果截图

这里写图片描述

6. 几个坑需要注意

1、两张表有相同的属性字段 name , 导致查询结果中 Classroomname 字段值会覆盖 Studentname 字段值, 因此出现如下现象:
这里写图片描述

问题出在 ClassroomMapper.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.tao.springmybatispostgresql.mapper.IClassroomMapper">

    <resultMap id="classroomResultMap" type="com.tao.springmybatispostgresql.entity.Classroom">
        <id property="id" column="c_id"/>
        <result property="classroomNo" column="classroom_no"/>
        <result property="name" column="name"/>

        <collection property="studentList" ofType="com.tao.springmybatispostgresql.entity.Student">
            <id property="id" column="s_id"/>
            <result property="studentNo" column="student_no"/>
            <result property="name" column="name"/>
            <result property="age" column="age"/>
            <result property="score" column="score"/>
            <result property="classroomNo" column="classroom_no"/>
        </collection>
    </resultMap>


    <select id="getClassroomByNo" parameterType="String" resultMap="classroomResultMap">
        SELECT
            c.id AS c_id,
            c.classroom_no,
            c.name,
            s.id AS s_id,
            s.student_no,
            s.name,
            s.age,
            s.score,
            s.classroom_no
        FROM tb_classroom c, tb_student s
        WHERE s.classroom_no = c.classroom_no AND c.classroom_no = #{classroomNo}
    </select>

</mapper>

解决办法:

对于相同的字段, 在写SQL的时候最好起不同的别名来区分!!!

修改之后的 ClassroomMapper.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.tao.springmybatispostgresql.mapper.IClassroomMapper">

    <resultMap id="classroomResultMap" type="com.tao.springmybatispostgresql.entity.Classroom">
        <id property="id" column="c_id"/>
        <result property="classroomNo" column="classroom_no"/>
        <result property="name" column="classroom_name"/>

        <collection property="studentList" ofType="com.tao.springmybatispostgresql.entity.Student">
            <id property="id" column="s_id"/>
            <result property="studentNo" column="student_no"/>
            <result property="name" column="student_name"/>
            <result property="age" column="age"/>
            <result property="score" column="score"/>
            <result property="classroomNo" column="classroom_no"/>
        </collection>
    </resultMap>


    <select id="getClassroomByNo" parameterType="String" resultMap="classroomResultMap">
        SELECT
            c.id AS c_id,
            c.classroom_no,
            c.name AS classroom_name,
            s.id AS s_id,
            s.student_no,
            s.name AS student_name,
            s.age,
            s.score,
            s.classroom_no
        FROM tb_classroom c, tb_student s
        WHERE s.classroom_no = c.classroom_no AND c.classroom_no = #{classroomNo}
    </select>

</mapper>

修改之后返回的数据不会存在覆盖的问题:
这里写图片描述


2、SQL文件没有问题, 但是无论如何 studentList 只输出一个 Student 对象.
这里写图片描述

这个问题出现的原因是 ClassroomStudent 表中有相同的字段 id:
对应的 ClassroomMapper.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.tao.springmybatispostgresql.mapper.IClassroomMapper">

    <resultMap id="classroomResultMap" type="com.tao.springmybatispostgresql.entity.Classroom">
        <id property="id" column="id"/>
        <result property="classroomNo" column="classroom_no"/>
        <result property="name" column="classroom_name"/>

        <collection property="studentList" ofType="com.tao.springmybatispostgresql.entity.Student">
            <id property="id" column="id"/>
            <result property="studentNo" column="student_no"/>
            <result property="name" column="student_name"/>
            <result property="age" column="age"/>
            <result property="score" column="score"/>
            <result property="classroomNo" column="classroom_no"/>
        </collection>
    </resultMap>


    <select id="getClassroomByNo" parameterType="String" resultMap="classroomResultMap">
        SELECT
            c.id,
            c.classroom_no,
            c.name AS classroom_name,
            s.id,
            s.student_no,
            s.name AS student_name,
            s.age,
            s.score,
            s.classroom_no
        FROM tb_classroom c, tb_student s
        WHERE s.classroom_no = c.classroom_no AND c.classroom_no = #{classroomNo}
    </select>

</mapper>

这个问题的解决办法是:

在写SQL的时候对两张表的 id 字段起别名, 避免使用相同的名!!!

修改之后的 ClassroomMapper.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.tao.springmybatispostgresql.mapper.IClassroomMapper">

    <resultMap id="classroomResultMap" type="com.tao.springmybatispostgresql.entity.Classroom">
        <id property="id" column="c_id"/>
        <result property="classroomNo" column="classroom_no"/>
        <result property="name" column="classroom_name"/>

        <collection property="studentList" ofType="com.tao.springmybatispostgresql.entity.Student">
            <id property="id" column="s_id"/>
            <result property="studentNo" column="student_no"/>
            <result property="name" column="student_name"/>
            <result property="age" column="age"/>
            <result property="score" column="score"/>
            <result property="classroomNo" column="classroom_no"/>
        </collection>
    </resultMap>


    <select id="getClassroomByNo" parameterType="String" resultMap="classroomResultMap">
        SELECT
            c.id AS c_id,
            c.classroom_no,
            c.name AS classroom_name,
            s.id AS s_id,
            s.student_no,
            s.name AS student_name,
            s.age,
            s.score,
            s.classroom_no
        FROM tb_classroom c, tb_student s
        WHERE s.classroom_no = c.classroom_no AND c.classroom_no = #{classroomNo}
    </select>

</mapper>

修改之后的返回结果恢复正常:
这里写图片描述

参考:
MyBatis的collection只能查询一条记录

猜你喜欢

转载自blog.csdn.net/hbtj_1216/article/details/80230032