结果集映射ResultMap
Mybtis中的结果集映射是一个强大的工具。在Mybatis官网有描述 “MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。”
1.数据库表与实体集不匹配
- 对于数据库中的表与实体集(POJO)的对象关系映射不一致是,ResultMap就有着巨大的作用。
-
在实体集中,我们发现实体集中的属性与数据库中的属性不匹配,在这忠情况下,我们需要使用实体集的映射功能。
-
使用步骤:
-
配置mapper接口和xml文件,将sql语句的xml文件注册到mybatis文件到映射器中。
备注:
<mappers> <mapper resource="com/xiaoli/dao/UserMapper.xml"/> <mapper resource="com/xiaoli/dao/StudentMapper.xml"/> </mappers>
-
需要注意的是,在类路径下配置的资源文件和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>
-
我们配置对象关系映射,创建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
testGetStudentById
-
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,我们不难发现,在表中存在两种对应关系:
-
多对一的关系
对于学生而言,使用多对一的关系
-
一对多的关系
对于老师而言,是一对多的关系
2.1.2 编码
-
创建项目,创建两个项目的实体集(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 + '}'; } }
-
编写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>
-
-
在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>
-
编写代码,测试目前会出现的问题
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字段为查询出结果,我们需要考虑多对一的关系。
-
处理字段为空情况
-
按结果嵌套处理
<?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 编码
-
创建项目,创建两个实体对象(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 + '}'; } }
-
编写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>
-
在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>
-
编写测试代码,查看我们目前出现的问题
代码:
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>
-
测试代码与测试结果
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(); } }
运行结果: