在JDK1.8中,当实体类属性名与数据表中的字段不一致时,我们如何查询数据?
实体类字段如下:
数据库字段如下:
查询结果:
解决这种问题,也很简单,下边记录两种方式(也是官方提供的):
方式一、
sql查询语句,使用as别名
<mapper namespace="com.lxc.dao.UserMapper">
<select id="getUserList" resultType="com.lxc.domain.User">
select id,
name,
password as psw
from mybatis
</select>
</mapper>
方式二、
使用resultMap 结果映射
把之前的 resultType 更换为 resultMap,使用<resultMap>标签来创建一个结果集。通过id来关联。
type:结果集的类型;
<result> 标签;
property:实体类中的属性名;
column:数据表中的字段;
<mapper namespace="com.lxc.dao.UserMapper">
<resultMap id="UserMap" type="com.lxc.domain.User">
<result property="psw" column="password" />
</resultMap>
<select id="getUserList" resultMap="UserMap">
select * from mybatis
</select>
</mapper>
官方描述:
一、多对一
1、
resultMap
元素是 MyBatis 中最重要最强大的元素。
想下下边如何查询出Student 学生和老师的信息:
数据表 - 多个学生对应一个老师:
Teacher类
package com.lxc.sprint_boot_01.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
}
Student类
package com.lxc.sprint_boot_01.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private int id;
private Teacher teacher;
}
Student实体类中有Teacher属性,这个属性对应就是教师对象,如果像之前一样查询,那么teacher属性查不出来,因为学生表中没有这样的字段,它是通过tid来关联 teacher表:
查询sql如下:
结果:
此时可以 resultMap 结果映射,下的 <association>表签或 <collection> 标签处理结果集,从而描述这种关系。
<!--type结果集的类型-->
<resultMap id="studentMap" type="com.lxc.sprint_boot_01.domain.Student">
<id column="id" property="id" />
<result column="name" property="name" />
<!--
(1)association描述一个对象,里边标签就是对象该有的字段;
(2)property = "teacher" student种的teacher属性
(3)javaType = "xx" 就是描述对象的类型
-->
<association property="teacher" javaType="com.lxc.sprint_boot_01.domain.Teacher">
<id column="tids" property="id" />
<result column="tname" property="name" />
</association>
</resultMap>
<select id="getStudentMapper" resultMap="studentMap">
select s.*, t.id as tids, t.name as tname from
student s,
teacher t
where s.tid = t.id;
</select>
此时查询出来的结果,符合预期:
2、
association
– 一个复杂类型的关联;许多结果将包装成这种类型- 嵌套结果映射 – 关联可以是
resultMap
元素,或是对其它结果映射的引用。
- 嵌套结果映射 – 关联可以是
collection
– 一个复杂类型的集合- 嵌套结果映射 – 集合可以是
resultMap
元素,或是对其它结果映射的引用。
- 嵌套结果映射 – 集合可以是
如果关联的结果为一个对象,那么使用 association;如果关联的结果为一个列表则使用 collection。
二、一对多
实体类属性改下,教师类中增加学生,它是一个泛型集合,因为对应的是多个学生。
对应的mapper.xml文件:
<collection> 对应的是结果集中的泛型列表;
property:为teacher类中的 studentList 字段;
ofType:这里与结果集是一个对象不同,当结果集其中的属性是一个泛型列表时,类型使用:ofType属性来表示。
<resultMap id="teacherMap" type="com.lxc.sprint_boot_01.domain.Teacher">
<id property="id" column="teachId" />
<result property="name" column="tname" />
<collection property="studentList" ofType="com.lxc.sprint_boot_01.domain.Student">
<id column="sid" property="id" />
<result column="sname" property="name" />
</collection>
</resultMap>
<select id="getTeacherMapper" resultMap="teacherMap">
select
t.id teachId, t.`name` tname,
s.id sid, s.name sname, s.tid stid
from
teacher t,
student s
where
t.id = s.tid
and
#{id} = s.tid;
</select>
查询结果为:
例一:
有四个表,分别时教师表、学生表、课程表、学生与课程关联中间表
根据id查询教师及对应的学生和学生对应的课程信息。
最后结果如下:
一个教师对象,里边有studentList数组,对应多个学生,学生中有textClass对象,对应课程信息。
这种看起来很复杂,如果明白了上边的多对一和一对多的使用,其实非常的简单,无非是使用resultMap 来描述一层层的关系。
下边是三个实体类:
Teacher
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
private int id;
private String name;
private List<Student> studentList;
}
Student
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private int id;
private TextClass textClass;
}
TextClass
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TextClass {
private int id;
private String english;
private String yuWen;
private String mathMatic;
}
对应的xml写法如下:
提示:有个技巧,如果多个表查询,关系比较乱的话,先在Navicat中,把sql语句写好,执行没问题了,在复制到xml中来;
其次,照着实体类来写他们之间的关系,比如下边:
查询的是教师,所以结果集是Teacher类型,字段就是Teacher中的字段,其中 studentList 字段是一个泛型集合,那么使用<collection>来描述,使用ofType来定义结果集类型,这里是Student类型,接着Student类中的字段,其中有textClass属性,这个属性对应的是TextClass类,是一个对象,那么使用<association>来描述对象,类型一定是TextClass类型的,里边写对应的 TextClass类中的字段即可,整个下来,思路很清晰。
<resultMap id="teacherMap" type="com.lxc.sprint_boot_01.domain.Teacher">
<id property="id" column="id" />
<result property="name" column="name" />
<collection property="studentList" ofType="com.lxc.sprint_boot_01.domain.Student">
<id column="sid" property="id" />
<result column="sname" property="name" />
<association property="textClass" javaType="com.lxc.sprint_boot_01.domain.TextClass">
<id column="cid" property="id" />
<result column="eng" property="english" javaType="String" />
<result column="mathM" property="mathMatic" javaType="String" />
<result column="yuWen" property="yuWen" javaType="String" />
</association>
</collection>
</resultMap>
<select id="getTeacherMapper" resultMap="teacherMap">
select
t.*,
s.id sid, s.`name` sname,
course.english eng, course.id cid, course.mathMatic mathM, course.yuWen yuWen
from
teacher t,
student s,
stuCourse sc,
course
where
#{id} = s.tid
and
s.id = sc.stuId
and
sc.courseId = course.id;
</select>