Myabtis中的ResultMap

结果集映射ResultMap

Mybtis中的结果集映射是一个强大的工具。在Mybatis官网有描述 “MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。”

1.数据库表与实体集不匹配

  • 对于数据库中的表与实体集(POJO)的对象关系映射不一致是,ResultMap就有着巨大的作用。

Myabtis中的ResultMap

  • 在实体集中,我们发现实体集中的属性与数据库中的属性不匹配,在这忠情况下,我们需要使用实体集的映射功能。

  • 使用步骤:

    1. 配置mapper接口和xml文件,将sql语句的xml文件注册到mybatis文件到映射器中。

      备注:

        <mappers>
              <mapper resource="com/xiaoli/dao/UserMapper.xml"/>
              <mapper resource="com/xiaoli/dao/StudentMapper.xml"/>
          </mappers>
      

      Myabtis中的ResultMap

    2. 需要注意的是,在类路径下配置的资源文件和xml文件可能会出现导出不了的问题,我们需要在pom.xml文件中添加配置文件。

      <!--导出文件失效问题解决-->
          <build>
              <resources>
                  <resource>
                      <directory>src/main/resources</directory>
                      <includes>
                          <include>**/*.properties</include>
                          <include>**/*.xml</include>
                      </includes>
                      <filtering>true</filtering>
                  </resource>
                  <resource>
                      <directory>src/main/java</directory>
                      <includes>
                          <include>**/*.properties</include>
                          <include>**/*.xml</include>
                      </includes>
                      <filtering>true</filtering>
                  </resource>
              </resources>
          </build>
      
    3. 我们配置对象关系映射,创建Mapper接口,创建mapper.xml配置文件

      StudentMapper接口

      package com.xiaoli.dao;
      
      import com.xiaoli.pojo.Student;
      import com.xiaoli.pojo.User;
      
      import java.util.List;
      
      public interface StudentMapper {
          //select查询语句
          public List<Student> getStudentList();
      
          //select条件查询
          public Student getStudentById(int id);
      }
      

      StudentMapper.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借口-->
      <mapper namespace="com.xiaoli.dao.StudentMapper">
      
          <!--
              结果集映射配置:
              1.resultMap:xml映射器
              2.id="":进行映射的类的别名,可以随意配置,但是需要注意与sql语句中的resultMap保持一致
              3.type:映射的数据类型(在该sql语句中,需要映射的是Student类)
          -->
          <resultMap id="getStudent" type="Student">
              <!--
              result:进行映射的字段
              property:实体集的属性
              column:数据库的字段名
               -->
              <result property="id" column="stu_id"/>
              <result property="name" column="stu_name"/>
              <result property="password" column="stu_password"/>
          </resultMap>
          <!--select查询语句-->
          <select id="getStudentList" resultMap="getStudent">
              select * from student
          </select>
      
          <!--条件查询-->
          <select id="getStudentById" parameterType="_int" resultMap="getStudent">
              select * from student where stu_id = #{id}
          </select>
      </mapper>
      

      4.测试,编写测试代码

      测试代码:

      package com.xiaoli.dao;
      
      import com.xiaoli.pojo.Student;
      import com.xiaoli.pojo.User;
      import com.xiaoli.util.MybatisUtil;
      import org.apache.ibatis.session.SqlSession;
      import org.junit.Test;
      
      import java.util.List;
      
      public class testStudentMapper {
      
          //select查询
          @Test
          public void testGetStudentList(){
              //获取SqlSession对象
              SqlSession sqlSession = MybatisUtil.getSqlSession();
      
              //  获取映射器
              StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      
              List<Student> studentList = mapper.getStudentList();
      
              //遍历
              for (Student student : studentList) {
                  System.out.println(student);
              }
              //关闭连接
              sqlSession.close();
      
          }
      
          //select条件查询
          @Test
          public void testGetStudentById(){
              //获取SqlSession对象
              SqlSession sqlSession = MybatisUtil.getSqlSession();
      
              //  获取映射器
              StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
      
              Student studentById = mapper.getStudentById(1);
      
              //遍历
              System.out.println(studentById);
      
              //关闭连接
              sqlSession.close();
      
          }
      }
      
      

      运行结果:

      testGetStudentList

      Myabtis中的ResultMap

      testGetStudentById

      Myabtis中的ResultMap

2.数据库表与数据库表的对应关系

2.1 多对一的关系

2.1.1 案例分析

现在我们需要对多对一进行分析,案例:

数据库中有两个实体:

stduent实体:

CREATE TABLE `student` (
  `id` int NOT NULL,
  `name` varchar(30) DEFAULT NULL,
  `tid` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师'); 

teacher实体:

CREATE TABLE `student` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');

通过创建的两个实体集:student与teacher,我们不难发现,在表中存在两种对应关系:

  • 多对一的关系

    Myabtis中的ResultMap

    ​ 对于学生而言,使用多对一的关系

  • 一对多的关系

    Myabtis中的ResultMap

    ​ 对于老师而言,是一对多的关系

2.1.2 编码

  1. 创建项目,创建两个项目的实体集(POPJO)

    Teacher实体集

    package com.xiaoli.pojo;
    
    public class Teacher {
        private int id;
        private String name;
    
        public Teacher() {
        }
    
        public Teacher(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Teacher{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    

    Stduent实体集
    备注:我们需要注意多对一的关系,学生中包含了老师的对象

    package com.xiaoli.pojo;
    
    public class Student {
        private int id;
        private String name;
        private Teacher teacher;//代表学生中含有一个老师,对应与student字段tid外键
    
        public Student() {
        }
    
        public Student(int id, String name, Teacher teacher) {
            this.id = id;
            this.name = name;
            this.teacher = teacher;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Teacher getTeacher() {
            return teacher;
        }
    
        public void setTeacher(Teacher teacher) {
            this.teacher = teacher;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", teacher=" + teacher +
                    '}';
        }
    }
    
    
  2. 编写mapper接口与mapper.xml配置文件(无论实体的mapper映射有没有用,都创建,以防万一)

    • TeacherMapper接口

      package com.xiaoli.dao;
      
      public interface TeacherMapper {
          
      }
      
      
    • TeacherMapper.xml配置文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <mapper namespace="com.xiaoli.dao.TeacherMapper">
      
      </mapper>
      
    • Studentmapper接口

      package com.xiaoli.dao;
      
      
      import com.xiaoli.pojo.Student;
      
      import java.util.List;
      
      public interface StudentMapper {
      }
      
      
    • StudentMapper.xml配置文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <mapper namespace="com.xiaoli.dao.StudentMapper">
      </mapper>
      
  3. 在config.xml配置文件中配置mapper映射器和为实体集添加别名(alias),方便以后使用

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <properties resource="db.properties"/>
    
        <typeAliases>
            <typeAlias type="com.xiaoli.pojo.Student" alias="Student"/>
            <typeAlias type="com.xiaoli.pojo.Teacher" alias="Teacher"/>
        </typeAliases>
    
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="com/xiaoli/dao/StudentMapper.xml"/>
            <mapper resource="com/xiaoli/dao/TeacherMapper.xml"/>
        </mappers>
    </configuration>
    
  4. 编写代码,测试目前会出现的问题

    StudentMapper

    package com.xiaoli.dao;
    
    
    import com.xiaoli.pojo.Student;
    
    import java.util.List;
    
    public interface StudentMapper {
        //查询所有学生以及学生的老师
        public List<Student> getStudentList();
    }
    

    StudentMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.xiaoli.dao.StudentMapper">
        <select id="getStudentList" resultType="Student">
            select * from student
        </select>
    </mapper>
    

    运行结果:我们发现teacher字段为查询出结果,我们需要考虑多对一的关系。

    Myabtis中的ResultMap

  5. 处理字段为空情况

    • 按结果嵌套处理

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <mapper namespace="com.xiaoli.dao.StudentMapper">
      
      <!--
          按结果嵌套处理:
          1.编写sql语句
          2.使用结果集映射:resultMap
      -->
          <resultMap id="getStudent" type="Student">
              <!--
                  property:对应实体集的属性
                  column:对应数据库sql语句的字段名
              -->
              <result property="id" column="sid"/>
              <result property="name" column="sname"/>
              <!--
                  association:表示该属性是对象
                  collection:表示该属性是集合
              -->
              <association property="teacher" javaType="Teacher">
                  <result property="id" column="tid"/>
                  <result property="name" column="tname"/>
              </association>
          </resultMap>
          <select id="getStudentList" resultMap="getStudent">
              select s.id sid,s.name sname,t.id tid,t.name tname
              from student s, teacher t
          </select>
      </mapper>
      
    • 按查询嵌套处理

      该方法不推荐,不是那么好懂
      

2.2 一对多的关系

2.2.1 案例分析

我们通过上面的案例分析,知道,在老师看来,老师与学生的关系是一对多的关系,即一个老师可以拥有多个学生。

2.2.2 编码

  1. 创建项目,创建两个实体对象(POJOP)

    Teacher实体集

    注意:我们需要注意一对多的问题,一个老师包含多个学生

    package com.xiaoli.pojo1;
    
    import java.util.List;
    
    public class Teacher {
        private int id;
        private String name;
    
        private List<Student> studentList;//一对多的关系,一个老师包含多个学生
    
        public Teacher() {
        }
    
        public Teacher(int id, String name, List<Student> studentList) {
            this.id = id;
            this.name = name;
            this.studentList = studentList;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public List<Student> getStudentList() {
            return studentList;
        }
    
        public void setStudentList(List<Student> studentList) {
            this.studentList = studentList;
        }
    
        @Override
        public String toString() {
            return "Teacher{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", studentList=" + studentList +
                    '}';
        }
    }
    

    Student实体

    package com.xiaoli.pojo1;
    
    public class Student {
        private int id;
        private String name;
        private int tid;
    
        public Student() {
        }
    
        public Student(int id, String name, int tid) {
            this.id = id;
            this.name = name;
            this.tid = tid;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getTid() {
            return tid;
        }
    
        public void setTid(int tid) {
            this.tid = tid;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", tid=" + tid +
                    '}';
        }
    }
    
  2. 编写mapper接口与mapper.xml配置文件(无论实体的mapper映射有没有用,都创建,以防万一)

    TeacherMapper接口

    package com.xiaoli.dao1;
    
    public class TeacherMapper {
    }
    
    

    TeacherMapper.xml配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.xiaoli.dao1.TeacherMapper">
    
    </mapper>
    

    StudentMapper接口

    package com.xiaoli.dao1;
    
    public class StudentMapper {
    
    }
    
    

    StudentMapper.xml配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.xiaoli.dao1.StudentMapper">
    
    </mapper>
    
  3. 在config.xml配置文件中配置mapper映射器和为实体集添加别名(alias),方便以后使用

    <typeAliases>
            <typeAlias type="com.xiaoli.pojo1.Student" alias="Student1"/>
            <typeAlias type="com.xiaoli.pojo1.Teacher" alias="Teacher1"/>
        </typeAliases>
    
    <mappers>
        <mapper resource="com/xiaoli/dao1/StudentMapper.xml"/>
        <mapper resource="com/xiaoli/dao1/TeacherMapper.xml"/>
    </mappers>
    
  4. 编写测试代码,查看我们目前出现的问题

    代码:

    StudentMapper接口

    package com.xiaoli.dao1;
    
    public interface StudentMapper {
    
    }
    
    

    StudentMapper.xml配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.xiaoli.dao1.StudentMapper">
    
    </mapper>
    

    TeacherMapper接口

    package com.xiaoli.dao1;
    
    import com.xiaoli.pojo1.Teacher;
    
    import java.util.List;
    
    public interface TeacherMapper {
    
        List<Teacher> getTeacherList();
    }
    
    

    TeacherMapper.xml配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.xiaoli.dao1.TeacherMapper">
    
        <!--
            步骤:
            1.编写sql语句
            2.进行结果集映射
        -->
        <resultMap id="getTeacher" type="Teacher1">
            <result property="id" column="tid"/>
            <result property="name" column="tname"/>
            <!--
               collection:代表集合   ofType:该属性的返回类型,在collection中使用
               association:代表对象  javaType:该属性的返回类型,在association中使用
            -->
            <collection property="studentList" ofType="Student1">
                <result property="id" column="sid"/>
                <result property="name" column="sname"/>
            </collection>
        </resultMap>
        <select id="getTeacherList" resultMap="getTeacher">
            select t.id tid,t.name tname,s.id sid,s.name sname from student s,teacher t
        </select>
    </mapper>
    
  5. 测试代码与测试结果

    package com.xioali.dao;
    
    import com.xiaoli.dao.StudentMapper;
    import com.xiaoli.dao1.TeacherMapper;
    import com.xiaoli.pojo.Student;
    import com.xiaoli.pojo1.Teacher;
    import com.xiaoli.util.MybatisUtil;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    public class testStudentMapper {
    
        //一对多的关系
        @Test
        public void testGetTeacherList(){
            SqlSession sqlSession = MybatisUtil.getSqlSession();
    
            TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
    
            List<Teacher> teacherList = mapper.getTeacherList();
    
            for (Teacher teacher : teacherList) {
                System.out.println(teacher);
            }
    
            sqlSession.close();
        }
    }
    
    

    运行结果:

    Myabtis中的ResultMap

上一篇:resultMap结果集映射解决属性名和字段不一致问题


下一篇:04_resultMap配置