mybatis中,可以使用collection和association来处理一对多和多对一的关系

其中每个标签中有2中种使用方式,一种是嵌套查询,一种是嵌套结果

嵌套查询会在主查询中,去调用子查询

嵌套结果只需要查询一次,将结果进行封装 

一、前提准备

1、数据库表

创建2张表,class和student,class和student是一对多

2张表的数据如下:

class:

student:

2、创建2个实体类对象

TClass

@Data
public class TClass extends Model<TClass> {
    private static final long serialVersionUID = 1L;
    private String id;
    private String name;
    private String code;

    @TableField(exist = false)
    List<TStudent> studentList;
}

TStudent

@Data
public class TStudent extends Model<TStudent> {
    private static final long serialVersionUID = 1L;
    private String id;
    private String name;
    private String card;
    private String classid;

    @TableField(exist = false)
    private TClass tClass;
}

 二、一对多

        一、嵌套结果 方式

         1、mapper接口

List<TClass> getClassList();

        2、service和serviceImpl省略

        3、xml文件

<!-- 嵌套结果 -->
<resultMap id="classMap1" type="com.example.aaa.test.entity.TClass">
    <id column="id" property="id" />
    <result column="name" property="name" />
    <result column="code" property="code" />
    <collection property="studentList" ofType="com.example.aaa.test.entity.TStudent">
        <id column="sid" property="id" />
        <result column="sname" property="name" />
        <result column="card" property="card" />
        <result column="classid" property="classid" />
    </collection>
</resultMap>

<select id="getClassList" resultMap="classMap1">
    SELECT
        c.id,
        c.name,
        c.code,
        s.id as sid,
        s.name as sname,
        s.card,
        s.classid
    FROM
        t_class c
    LEFT JOIN t_student s ON s.classid = c.id
</select>

嵌套结果,在使用的时候需要注意名称相同的字段,需要用别名,在result的column中,需要使用对应的别名

        二、嵌套查询 方式

        1、mapper接口

List<TClass> getClasses();

        2、service接口和serviceImpl省略

        3、xml文件

<resultMap id="classMap2" type="com.example.aaa.test.entity.TClass">
    <id column="id" property="id" />
    <result column="name" property="name" />
    <result column="code" property="code" />
    <collection property="studentList"
                column="{sid=id}"
                select="getStudentByCid"
                ofType="com.example.aaa.test.entity.TStudent">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="card" property="card" />
        <result column="classid" property="classid" />
    </collection>
</resultMap>

<!--主查询-->
<select id="getClasses" resultMap="classMap2">
    select id,name,code from t_class;
</select>

<!--子查询-->
<select id="getStudentByCid" resultType="com.example.aaa.test.entity.TStudent">
    select id,name,card,classid from t_student where classid=#{sid};
</select>

collection标签的解释:

1.property是子查询封装的结果,对应到主查询的哪个属性

2.column是将查询结果中的参数,传递到子查询中{sid=id},id必须出现在父查询的结果集中,子查询中要使用sid

3.select是调用的子查询的语句,不需要在mapper接口中额外添加

4.ofType是封装的List集合中对象的类型

4、controller调用

    @RequestMapping("/getClassList")
    public Object getStudentList(){
        List<TClass> list = tClassService.getClassList();
        return list;
    }

    @RequestMapping("/getClasses")
    public Object getStudens(){
        List<TClass> list = tClassService.getClasses();
        return list;
    }

嵌套结果和嵌套查询,查询结果一样,如图:

三、多对一

        一、嵌套结果 方式

        1、mapper接口

List<TStudent> getStudentList();

        2、service和serviceImpl省略

        3、xml文件

<!-- 嵌套结果 -->
<resultMap id="StudentMap1" type="com.example.aaa.test.entity.TStudent">
    <id column="id" property="id" />
    <result column="name" property="name" />
    <result column="card" property="card" />
    <result column="classid" property="classid" />

    <association property="tClass" javaType="com.example.aaa.test.entity.TClass">
        <!-- 含义:cid对应的是TClass类中的id;column=cid是查出结果中的别名,因为id和上面的id重名,所以用别名 -->
        <id column="cid" property="id"></id>
        <!-- 同理,cname也需要用别名,因为和上面的name重复了 -->
        <result column="cname" property="name" />
        <!-- code不需要别名,因为code是唯一的 -->
        <result column="code" property="code" />
    </association>
</resultMap>

<select id="getStudentList" resultMap="StudentMap1">
    SELECT
        s.id,
        s.name,
        s.classid,
        s.card,
        c.id AS cid,
        c.name AS cname,
        c.code
    FROM
        t_student s
    LEFT JOIN t_class c ON s.classid = c.id
</select>

        二、嵌套查询 方式

        1、mapper接口

List<TClass> getClasses();

        2、service和serviceImpl省略

        3、xml文件

<!--嵌套查询-->
<resultMap id="StudentMap2" type="com.example.aaa.test.entity.TStudent">
    <id column="id" property="id" />
    <result column="name" property="name" />
    <result column="card" property="card" />
    <result column="classid" property="classid" />
    <!--
       property=tClass是Student中的属性
       select="getClassBySid"是要调用的子查询
       column="{cid=classid}"是要传入子查询中的参数,就是结果集中的classid赋值给cid,子查询用cid查询
       JavaType是子查询结果的类型
    -->
    <association property="tClass"
                 column="{cid=classid}"
                 javaType="com.example.aaa.test.entity.TClass"
                 select="getClassBySid">
        <!--不会出现重名,所以不需要改别名-->
        <id column="id" property="id"></id>
        <result column="name" property="name" />
        <result column="code" property="code" />
    </association>
</resultMap>

<select id="getStudents" resultMap="StudentMap2">
    SELECT
        id,
        name,
        classid,
        card
    FROM
        t_student
</select>

<!--子查询不需要在mapper的接口中额外添加-->
<select id="getClassBySid" resultType="com.example.aaa.test.entity.TClass">
    SELECT
        id,
        name,
        code
    FROM t_class
    <!--cid是从父查询传递过来的-->
    where id=#{cid}
</select>

4、controller调用

    @RequestMapping("/getStudentList")
    public Object getStudentList(){
        List<TStudent> list = tStudentService.getStudentList();
        return list;
    }

    @RequestMapping("/getStudents")
    public Object getStudens(){
        List<TStudent> list = tStudentService.getStudents();
        return list;
    }

嵌套结果和嵌套查询,查询结果相同,如图:

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐