MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】

前言:部分参考自https://www.bilibili.com/video/BV1NE411Q7Nx?p=20

文章目录

ResultMap结果集映射

一、解决属性名和字段名不一致的问题

1、问题背景

解决属性名和字段名不一致的问题

user表
MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】
User实体类

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

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
//    private String pwd;
    //注:此处与数据库中字段pwd不同名,字段不一致
    private String password;
}

将User实体类中的 pwd 改成 password,使其与数据库中字段 pwd 无法对应,从而问题产生
MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】
MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】
password 结果为null
MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】

2、解决方法

方法1:AS指定别名

为列名指定别名 , 别名和java实体类的属性名一致

<select id="selectUserById" resultType="User">
	SELECT id, name, pwd AS password FROM user WHERE id = #{id}
</select>

方法2(推荐):ResultMap结果集映射

ResultMap结果集映射

<!--结果集映射-->
<resultMap id="UserMap" type="com.zlc.pojo.User">
    <!--column:数据库中的字段,property:实体类中的属性-->
    <result column="pwd" property="password"/>
</resultMap>

<!--id:接口方法的名字-->
<select id="getUserById" parameterType="int" resultMap="UserMap">
    SELECT * FROM user WHERE id = #{id};
</select>

以上两种方法,都可以实现不同名字段的一一对应
MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】

3、ResultMap结果集映射

  • resultMap 元素是 MyBatis 中最重要最强大的元素。
  • ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了
  • ResultMap 的优秀之处——你完全可以不用显式地配置它们

resultMap 元素有很多子元素和一个值得深入探讨的结构,称为高级结果映射,具体可参考官方文档
MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】

二、解决JavaBean中的复杂属性

【多对一的情况】

例子:多位学生对应一位老师

Student类中关键语句:private Teacher teacher;

1、问题背景

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Student {
    private int id;
    private String name;
    private Teacher teacher;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Teacher {
    private int id;
    private String name;
}

StudentMapper接口

public interface StudentMapper {
    public List<Student> getAllStudents();
}

StudentMapper.xml

<select id="getAllStudents" resultType="student">
    SELECT s.id, s.name, t.name 
    FROM student s, teacher t 
    WHERE s.tid = t.id
</select>

测试类

@Test
public void testGetAllStudents() {
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    List<Student> students = mapper.getAllStudents();
    for (Student student : students) {
        System.out.println(student);
    }
    System.out.println();
    sqlSession.close();
}

MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】
之所以Student对象的teacher属性为null,是因为只有查询出的s.id,s.name属性可以一一映射到Student对象中,而t.name属性无法找到其映射,且Student对象teacher属性未被赋值,因此为null
MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】

2、解决方法

方法一:按照查询嵌套处理

思路:

  • 1、查询所有学生的信息
  • 2、根据查询出的学生的tid,再查出对应老师

首先更改StudentMapper.xml,新建一个ResultMap结果集映射,实现Student对象中复杂属性teacher的绑定,并将此ResultMap写入查询学生表的select的属性中,以替代之前的resultType = student

<!--
   1、查询所有学生的信息
   2、根据查询出的学生的tid,再查出对应老师
-->
<resultMap id="StudentTeacher" type="student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <!--复杂的属性,单独处理
        对象:association
        集合:collection
    -->
    <association property="teacher" column="tid" javaType="teacher" select="getTeacherById"/>
</resultMap>

<select id="getAllStudents" resultMap="StudentTeacher">
    SELECT * FROM student
</select>

<select id="getTeacherById" resultType="teacher">
    SELECT * FROM teacher WHERE id = #{id}
</select>

便可成功查出
MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】
附加:表中数据如下图
MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】

方法二:按照结果嵌套处理(推荐)

更改StudentMapper.xml

<select id="getAllStudents2" resultMap="StudentTeacher2">
    SELECT s.id sid, s.name sname, t.name tname, t.id tid
    FROM student s, teacher t
    WHERE s.tid = t.id
</select>

<resultMap id="StudentTeacher2" 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>

MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】

【一对多的情况】

例子:一位老师对应多位学生

Teacher类中关键语句:private List<Student> students;

1、问题背景

和上述几个问题的情况一样,也是null问题,不再赘述,之间上所有关键代码

2、解决方法

方法:按照结果嵌套处理

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Student {
    private int id;
    private String name;
    private int tid;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Teacher {
    private int id;
    private String name;
    //一个老师对应多个学生
    private List<Student> students;
}

TeacherMapper.xml

<select id="getTeacherById" resultMap="TeacherStudent">
    SELECT s.id sid, s.name sname, t.name tname, t.id tid
    FROM student s, teacher t
    WHERE s.tid = t.id AND t.id = #{tid}
</select>

<resultMap id="TeacherStudent" type="teacher">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <!--
        javaType:指定属性类型
        ofType:集合中的泛型信息
    -->
    <collection property="students" ofType="student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
    </collection>
</resultMap>

测试类

@Test
public void getTeacherById() {
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
    Teacher teacher = mapper.getTeacherById(1);
    System.out.println(teacher);
    System.out.println();
    sqlSession.close();
}

MyBatis知识汇总(第八篇)ResultMap结果集映射+复杂属性映射【多对一的情况】【一对多的情况】

上一篇:封装


下一篇:Spring中的循环依赖解决详解