resultMap是mybatis中最复杂的元素之一,它描述如何从结果集中加载对象,主要作用是定义映射规则、级联的更新、定制类型转化器。
resultMap参数讲解
constructor: 用于配置构造器方法
id: 将结果集标记为id,以方便全局调用
result: 配置POJO到数据库列名映射关系
association: 级联使用 代表多对一关系
collection: 级联使用 代表一对多关系
discriminator: 级联使用 鉴别器 根据实际选择实例,可以通过特定条件确定结果集
一、通过xml的方式实现结果映射
我们就以学生跟班级的关系来测试
学生表:
班级表:
1.创建一个学生实体类
package cn.et.demo03.xml.model;
public class Student {
private String id;
private String name;
private Grade grade;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
2.创建一个班级类
package cn.et.demo03.xml.model;
import java.util.ArrayList;
import java.util.List;
public class Grade {
private String id;
private String name;
private List<Student> list =new ArrayList<Student>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Student> getList() {
return list;
}
public void setList(List<Student> list) {
this.list = list;
}
}
在后台的JavaBean中,如果遵守规范的话,属性名和列名一致,那么我们就不需要手动做字段映射,MyBatis会自动帮我们把值填充到Bean中。但现在情况不一样,Bean的属性名和数据库列名对应不上。所以我们需要自己去映射
用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 namespace="cn.et.demo03.xml.mapper.StudentMapper">
<!--
结果集映射:
数据库的列名和实体类的属性名 如果不一致 需要建立列名和属性名的映射关系
结果集映射返回的结果是相同的 都是classes 只是多了一层关系
-->
<resultMap id="studentMap" type="cn.et.demo03.xml.model.Student">
<id column="sid" property="name"></id>
<result column="sname" property="name"></result>
<association column="gid" property="grade" select="cn.et.demo03.xml.mapper.GradeMapper.gradeById"></association>
</resultMap>
<select id="ManyToOneById" resultMap="studentMap">
select * from student where sid=#{id}
</select>
</mapper>
<?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 namespace="cn.et.demo03.xml.mapper.GradeMapper">
<resultMap id="gradeMap" type="cn.et.demo03.xml.model.Grade">
<id column="gid" property="id"></id>
<result column="gname" property="name"></result>
</resultMap>
<select id="gradeById" resultMap="gradeMap">
select * from grade where gid=#{id}
</select>
</mapper>
id : 唯一标识,一般用来标识id
column: 用来标识数据库的字段名
property: 用来标识实体的字段名
association: 代表一对多的关系
selele: 用来标识sql语句所在的位置
写一个测试类
package cn.et.demo03.xml.controller;
import cn.et.demo03.xml.mapper.GradeMapper;
import cn.et.demo03.xml.mapper.StudentMapper;
import cn.et.demo03.xml.model.Grade;
import cn.et.demo03.xml.model.Student;
import cn.et.tools.DBTools;
import java.io.IOException;
public class TestController {
public static void main(String[] args) throws IOException {
// 一对多的例子
Grade grade =OneToMany();
System.out.println("班级名称:"+grade.getName());
for (int i=0; i<grade.getList().size(); i++){
System.out.println("学生姓名:"+grade.getList().get(i).getName());
}
}
/**
* 多对一的例子
* @return
* @throws IOException
*/
public static Student ManyToOne() throws IOException {
StudentMapper studentMapper = DBTools.getSession().getMapper(StudentMapper.class);
Student student =studentMapper.ManyToOneById("11");
return student;
}
}
结果:
用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 namespace="cn.et.demo03.xml.mapper.GradeMapper">
<!--一对多的实现例子-->
<resultMap id="oneToManyMap" type="cn.et.demo03.xml.model.Grade">
<id column="gid" property="id"></id>
<result column="gname" property="name"></result>
<collection property="list" column="gid" javaType="arraylist" select="cn.et.demo03.xml.mapper.StudentMapper.studentByGid"></collection>
</resultMap>
<select id="oneToMany" resultMap="oneToManyMap">
select * from grade where gid=#{id}
</select>
</mapper>
<?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 namespace="cn.et.demo03.xml.mapper.StudentMapper">
<!--一对多的例子-->
<resultMap id="studentByGidMap" type="cn.et.demo03.xml.model.Student">
<id column="sid" property="name"></id>
<result column="sname" property="name"></result>
</resultMap>
<select id="studentByGid" resultMap="studentByGidMap">
select * from student where gid=#{id}
</select>
</mapper>
collection:用来标识一对多的关系
javaType:用来指定返回的类型
select: 用来标识sql语句的路径
编写一个测试类
package cn.et.demo03.xml.controller;
import cn.et.demo03.xml.mapper.GradeMapper;
import cn.et.demo03.xml.mapper.StudentMapper;
import cn.et.demo03.xml.model.Grade;
import cn.et.demo03.xml.model.Student;
import cn.et.tools.DBTools;
import java.io.IOException;
public class TestController {
public static void main(String[] args) throws IOException {
// 多对一的例子
Student student = ManyToOne();
System.out.println(student.getName()+"===="+student.getGrade().getName());
}
/**
* 多对一的例子
* @return
* @throws IOException
*/
public static Student ManyToOne() throws IOException {
StudentMapper studentMapper = DBTools.getSession().getMapper(StudentMapper.class);
Student student =studentMapper.ManyToOneById("11");
return student;
}
}
效果:
鉴别器的讲解
<?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 namespace="cn.et.demo03.xml.mapper.StudentMapper">
<!--鉴别器 判断返回数据,如果sid等于11就使用test1的resultMap,如果sid等于22就使用test2的resultMap-->
<resultMap id="test" type="cn.et.demo03.xml.model.Student">
<discriminator column="sid" javaType="string">
<case value="11" resultMap="test1"/>
<case value="22" resultMap="test2"/>
</discriminator>
</resultMap>
<resultMap id="test1" type="cn.et.demo03.xml.model.Student">
<result property="id" column="sid"/>
</resultMap>
<resultMap id="test2" type="cn.et.demo03.xml.model.Student">
<result property="name" column="sname"></result>
</resultMap>
<select id="test" resultMap="test">
select * from student where sid= #{id}
</select>
</mapper>
鉴别器就用来判断返回值的,如果判断返回值如果等于一就执行一的resultMap,等于二就执行二的resultMap
case:就相当于if里面的条件,如果返回的参数登录case里面的valse就执行满足的这个case的resultMap
二、通过注解的方式来实现结果集映射
首先还是一样创建班级、学生两个实体类
package cn.et.demo03.annotation.model;
import java.util.ArrayList;
import java.util.List;
public class Grade {
private String id;
private String name;
private List<Student> list =new ArrayList<Student>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Student> getList() {
return list;
}
public void setList(List<Student> list) {
this.list = list;
}
}
package cn.et.demo03.annotation.model;
public class Student {
private String id;
private String name;
private Grade grade;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
用注解的方式比用xml的方式要简洁,直接在接口文件里面写就可以了
演示一对多的关系
package cn.et.demo03.annotation.mapper;
import cn.et.demo03.annotation.model.Grade;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface GradeMapper {
/**
* 演示一对多的接口
* @param id
* @return
*/
@Results({
@Result(property = "id",column = "gid"),
@Result(property = "name",column = "gname"),
@Result(property = "list",column ="gid",javaType = List.class, many = @Many(select = "cn.et.demo03.annotation.mapper.StudentMapper.studentByGid"))
})
@Select("select * from grade where gid =#{id}")
Grade oneToMany(@Param("id") String id);
}
package cn.et.demo03.annotation.mapper;
import cn.et.demo03.annotation.model.Student;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface StudentMapper {
/**
* 演示一对多
* @param id
* @return
*/
@Results({
@Result(property = "id",column = "sid"),
@Result(property = "name",column = "sname")
})
@Select("select * from student where gid=#{id}")
List<Student> studentByGid(@Param("id") String id);
}
参数跟刚刚xml的方式意思差不多,就是用法不一样而已,按照如上操作 然后自己写一个测试类就实现了一对多的结果映射了。
演示多对一
package cn.et.demo03.annotation.mapper;
import cn.et.demo03.annotation.model.Student;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface StudentMapper {
/**
* 演示多对一
* @param id
* @return
*/
@Results({
@Result(property = "id",column = "sid"),
@Result(property = "name",column = "sname"),
@Result(property = "grade",column = "gid",one = @One(select = "cn.et.demo03.annotation.mapper.GradeMapper.gradeById"))
})
@Select("select * from student where sid= #{id}")
Student ManyToOneById(@Param("id") String id);
}
package cn.et.demo03.annotation.mapper;
import cn.et.demo03.annotation.model.Grade;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface GradeMapper {
/**
* 演示多对一的接口
* 通过班级id查找班级详细信息
* @param id
* @return
*/
@Results({
@Result(property = "id",column = "gid"),
@Result(property = "name",column = "gname")
})
@Select("select * from grade where gid= #{id}")
Grade gradeById(@Param("id") String id);
}