有时侯,我们用SQL取得的结果需要映射到类似Map<key, Bean>这样的数据结构中或是映射到多个实体类中时,我们就需要使用到resultMap。下面用3个例子说明Mybatis高级结果映射的用法。

<环境准备>

请参照上一篇blog<Mybatis Guide>

<数据准备>

创建班级--学生表的一对多的数据结构

 --创建班级表
CREATE TABLE tempdb..test_class
(
class_id int NOT NULL PRIMARY KEY,
class_name varchar(255),
class_admin_name varchar(255)
);
--创建学生表
CREATE TABLE tempdb..test_student
(
student_id int NOT NULL PRIMARY KEY,
class_id int,
student_name varchar(255),
student_age int,
student_address varchar(255)
);
--班级表中插入数据
insert tempdb..test_class values (101, 'Class 1, Grade 1', 'Mr. Zhang');
insert tempdb..test_class values (102, 'Class 2, Grade 1', 'Mr. Li');
insert tempdb..test_class values (103, 'Class 3, Grade 1', 'Mr. Wang');
insert tempdb..test_class values (201, 'Class 1, Grade 2', 'Mr. Zhao');
insert tempdb..test_class values (202, 'Class 2, Grade 2', 'Mr. Liu');
--学生表中插入数据
insert tempdb..test_student values (101001, 101, 'Name 1', 20, 'Address 1');
insert tempdb..test_student values (101002, 101, 'Name 2', 21, 'Address 2');
insert tempdb..test_student values (101003, 101, 'Name 3', 20, 'Address 3');
insert tempdb..test_student values (102001, 102, 'Name 4', 22, 'Address 4');
insert tempdb..test_student values (102002, 102, 'Name 5', 21, 'Address 5');
insert tempdb..test_student values (201001, 201, 'Name 6', 23, 'Address 6');
insert tempdb..test_student values (201002, 201, 'Name 7', 22, 'Address 7');
insert tempdb..test_student values (202001, 202, 'Name 8', 22, 'Address 8');

<创建实体类Entity>

 package mybatistest;

 import java.io.Serializable;

 public class Clazz implements Serializable {

     private static final long serialVersionUID = 1L;

     private Integer classId;

     private String className;

     private String classAdminName;

     public Integer getClassId() {
return classId;
} public void setClassId(Integer classId) {
this.classId = classId;
} public String getClassName() {
return className;
} public void setClassName(String className) {
this.className = className;
} public String getClassAdminName() {
return classAdminName;
} public void setClassAdminName(String classAdminName) {
this.classAdminName = classAdminName;
} @Override
public String toString() {
return "Clazz [classId=" + classId + ", className=" + className + ", classAdminName=" + classAdminName + "]";
}
}

Class

 package mybatistest;

 import java.io.Serializable;

 public class Student implements Serializable {

     private static final long serialVersionUID = 1L;

     private Integer studentId;

     private Integer classId;

     private String studentName;

     private Integer studentAge;

     private String studentAddress;

     public Integer getStudentId() {
return studentId;
} public void setStudentId(Integer studentId) {
this.studentId = studentId;
} public String getStudentName() {
return studentName;
} public Integer getClassId() {
return classId;
} public void setClassId(Integer classId) {
this.classId = classId;
} public void setStudentName(String studentName) {
this.studentName = studentName;
} public Integer getStudentAge() {
return studentAge;
} public void setStudentAge(Integer studentAge) {
this.studentAge = studentAge;
} public String getStudentAddress() {
return studentAddress;
} public void setStudentAddress(String studentAddress) {
this.studentAddress = studentAddress;
} @Override
public String toString() {
return "Student [classId=" + classId + ", studentId=" + studentId + ", studentName=" + studentName
+ ", studentAge=" + studentAge + ", studentAddress=" + studentAddress + "]";
}
}

Student

<创建StudentsPerClass(OutputBean)>

创建一个Class的OutBean,其中包含classId,Class实体类,及Student实体类List以对应班级--学生的1对多关系。

 package mybatistest;

 import java.io.Serializable;
import java.util.List; public class StudentsPerClass implements Serializable { private static final long serialVersionUID = 1L; private Integer classId; private Clazz clazz; private List<Student> students; public Integer getClassId() {
return classId;
} public void setClassId(Integer classId) {
this.classId = classId;
} public Clazz getClazz() {
return clazz;
} public void setClazz(Clazz clazz) {
this.clazz = clazz;
} public List<Student> getStudents() {
return students;
} public void setStudents(List<Student> students) {
this.students = students;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder(
"StudentsPerClass [classId=" + classId + ", clazz=" + clazz + ", students=" + System.lineSeparator());
students.forEach(p -> {
sb.append("--").append(p).append(System.lineSeparator());
});
return sb.append("]").toString();
}
}

StudentsPerClass

<创建三个SQL实例>

(1) 用Map<学号, 学生实体类>映射一个学生集合

(2) 用List<StudentsPerClass>映射班级--学生的1对多关系

(3) 用Map<班级号, StudentsPerClass>映射班级--学生集合

ClassStudentRepository.java

 package mybatistest;

 import java.util.List;
import java.util.Map; import org.apache.ibatis.annotations.MapKey; public interface ClassStudentRepository { // 获取一个班级的所有学生[Map<[Student Id], [Student Info]>]
@MapKey("studentId")
Map<Integer, Student> getStudentsFromOneClass(Integer classId); // 获取一个年级的所有学生
List<StudentsPerClass> getStudentsFromOneGrade(Integer gradeId); // 获取所有学生
@MapKey("classId")
Map<Integer, StudentsPerClass> getAllStudents();
}

ClassStudentRepository.xml

注意黄色部分非常重要,只有设置了1对多关系中的主键class_id,Mybatis才能自动映射这种1对多的嵌套关系

 <?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="mybatistest.ClassStudentRepository">
<!-- // 获取一个班级的所有学生[Map<[Student Id], [Student Info]>] -->
<select id="getStudentsFromOneClass" resultMap="studentsFromOneClassMap">
SELECT
t2.student_id,
t2.class_id,
t2.student_name,
t2.student_age,
t2.student_address
FROM
tempdb..test_class t1
INNER JOIN
tempdb..test_student t2
ON
t1.class_id = t2.class_id
WHERE
t1.class_id = #{classId}
</select>
<resultMap id="studentsFromOneClassMap" type="mybatistest.Student">
<id property="studentId" column="student_id" />
<result property="classId" column="class_id" />
<result property="studentName" column="student_name" />
<result property="studentAge" column="student_age" />
<result property="studentAddress" column="student_address" />
</resultMap> <!-- 获取一个年级的所有学生 -->
<select id="getStudentsFromOneGrade" resultMap="studentsFromOneGradeMap">
SELECT
t1.class_id,
t1.class_name,
t1.class_admin_name,
t2.student_id,
t2.student_name,
t2.student_age,
t2.student_address
FROM
tempdb..test_class t1
INNER JOIN
tempdb..test_student t2
ON
t1.class_id = t2.class_id
WHERE
t1.class_id/100 = #{gradeId}
</select>
<resultMap id="studentsFromOneGradeMap" type="mybatistest.StudentsPerClass">
<id property="classId" column="class_id"/>
<association property="clazz" javaType="mybatistest.Clazz" >
<id property="classId" column="class_id"/>
<result property="className" column="class_name"/>
<result property="classAdminName" column="class_admin_name"/>
</association>
<collection property="students" ofType="mybatistest.Student">
<id property="studentId" column="student_id" />
<result property="classId" column="class_id"/>
<result property="studentName" column="student_name" />
<result property="studentAge" column="student_age" />
<result property="studentAddress" column="student_address" />
</collection>
</resultMap> <!-- 获取所有学生 -->
<select id="getAllStudents" resultMap="allStudentsMap">
SELECT
t1.class_id,
t1.class_name,
t1.class_admin_name,
t2.student_id,
t2.student_name,
t2.student_age,
t2.student_address
FROM
tempdb..test_class t1
INNER JOIN
tempdb..test_student t2
ON
t1.class_id = t2.class_id
</select>
<resultMap id="allStudentsMap" type="mybatistest.StudentsPerClass">
<id property="classId" column="class_id"/>
<association property="clazz" javaType="mybatistest.Clazz" >
<id property="classId" column="class_id"/>
<result property="className" column="class_name"/>
<result property="classAdminName" column="class_admin_name"/>
</association>
<collection property="students" ofType="mybatistest.Student">
<id property="studentId" column="student_id" />
<result property="classId" column="class_id"/>
<result property="studentName" column="student_name" />
<result property="studentAge" column="student_age" />
<result property="studentAddress" column="student_address" />
</collection>
</resultMap>
</mapper>

mybatis-config.xml中添加映射关系

     <mappers>
<mapper resource="mybatistest/ClassStudentRepository.xml" />
</mappers>

<测试结果>

 package mybatistest;

 import java.util.List;
import java.util.Map; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory; public class MainTest { public static void main(String[] args) {
SqlSessionFactory sqlSessionFactory = MybatisTestSessionFactory.getSqlSessionFactoryInstance();
SqlSession session = sqlSessionFactory.openSession();
ClassStudentRepository classStudentRepository = session.getMapper(ClassStudentRepository.class);
Map<Integer, Student> res1 = classStudentRepository.getStudentsFromOneClass(102);
res1.forEach((p, q) -> {
System.out.println("Student ID: " + p + "; Student info: " + q);
});
// [Output]
// Student ID: 102001; Student info: Student [classId=102, studentId=102001, studentName=Name 4, studentAge=22, studentAddress=Address 4]
// Student ID: 102002; Student info: Student [classId=102, studentId=102002, studentName=Name 5, studentAge=21, studentAddress=Address 5]
List<StudentsPerClass> res2 = classStudentRepository.getStudentsFromOneGrade(1);
res2.forEach((p) -> {
System.out.println(p);
});
// [Output]
// StudentsPerClass [classId=101, clazz=Clazz [classId=101, className=Class 1, Grade 1, classAdminName=Mr. Zhang], students=
// --Student [classId=101, studentId=101001, studentName=Name 1, studentAge=20, studentAddress=Address 1]
// --Student [classId=101, studentId=101002, studentName=Name 2, studentAge=21, studentAddress=Address 2]
// --Student [classId=101, studentId=101003, studentName=Name 3, studentAge=20, studentAddress=Address 3]
// ]
// StudentsPerClass [classId=102, clazz=Clazz [classId=102, className=Class 2, Grade 1, classAdminName=Mr. Li], students=
// --Student [classId=102, studentId=102001, studentName=Name 4, studentAge=22, studentAddress=Address 4]
// --Student [classId=102, studentId=102002, studentName=Name 5, studentAge=21, studentAddress=Address 5]
// ]
Map<Integer, StudentsPerClass> res3 = classStudentRepository.getAllStudents();
res3.forEach((p, q) -> {
System.out.println("Class ID: " + p + System.lineSeparator() + q);
});
// [Output]
// Class ID: 101
// StudentsPerClass [classId=101, clazz=Clazz [classId=101, className=Class 1, Grade 1, classAdminName=Mr. Zhang], students=
// --Student [classId=101, studentId=101001, studentName=Name 1, studentAge=20, studentAddress=Address 1]
// --Student [classId=101, studentId=101002, studentName=Name 2, studentAge=21, studentAddress=Address 2]
// --Student [classId=101, studentId=101003, studentName=Name 3, studentAge=20, studentAddress=Address 3]
// ]
// Class ID: 102
// StudentsPerClass [classId=102, clazz=Clazz [classId=102, className=Class 2, Grade 1, classAdminName=Mr. Li], students=
// --Student [classId=102, studentId=102001, studentName=Name 4, studentAge=22, studentAddress=Address 4]
// --Student [classId=102, studentId=102002, studentName=Name 5, studentAge=21, studentAddress=Address 5]
// ]
// Class ID: 201
// StudentsPerClass [classId=201, clazz=Clazz [classId=201, className=Class 1, Grade 2, classAdminName=Mr. Zhao], students=
// --Student [classId=201, studentId=201001, studentName=Name 6, studentAge=23, studentAddress=Address 6]
// --Student [classId=201, studentId=201002, studentName=Name 7, studentAge=22, studentAddress=Address 7]
// ]
// Class ID: 202
// StudentsPerClass [classId=202, clazz=Clazz [classId=202, className=Class 2, Grade 2, classAdminName=Mr. Liu], students=
// --Student [classId=202, studentId=202001, studentName=Name 8, studentAge=22, studentAddress=Address 8]
// ]
session.close();
}
}

Mybatis高级结果映射的更多相关文章

  1. Mybatis 高级结果映射 ResultMap Association Collection

    在阅读本文章时,先说几个mybatis中容易混淆的地方: 1. mybatis中的列不是数据库里的列而是查询里的列,可以是别名(如 select user_name as userName,这时col ...

  2. 转:mybatis 高级结果映射(http://blog.csdn.net/ilovejava_2010/article/details/8180521)

    高级结果映射 MyBatis的创建基于这样一个思想:数据库并不是您想怎样就怎样的.虽然我们希望所有的数据库遵守第三范式或BCNF(修正的第三范式),但它们不是.如果有一个数据库能够完美映射到所有应用程 ...

  3. MyBatis从入门到精通(十一):MyBatis高级结果映射之一对多映射

    最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解MyBatis中如何使 ...

  4. MyBatis从入门到精通(九):MyBatis高级结果映射之一对一映射

    最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 本篇博客主要讲解MyBatis中实现查 ...

  5. MyBatis高级查询

    -------------------------siwuxie095 MyBatis 高级查询 1.MyBatis 作为一个 ORM 框架,也对 SQL 的高级查询做了支持, MyBatis 高级查 ...

  6. 【Mybatis高级映射】一对一映射、一对多映射、多对多映射

    前言 当我们学习heribnate的时候,也就是SSH框架的网上商城的时候,我们就学习过它对应的高级映射,一对一映射,一对多映射,多对多映射.对于SSM的Mybatis来说,肯定也是差不多的.既然开了 ...

  7. 六 mybatis高级映射(一对一,一对多,多对多)

    1  订单商品数据模型 以订单商品数据为模型,来对mybaits高级关系映射进行学习.

  8. mybatis高级映射(一对一,一对多)

    mybatis高级映射 一对一关联映射 需求:查询订单信息,关联查询用户信息(一个订单对应一个用户) (1)通过resultType实现 sql语句: select orders.* , USER.u ...

  9. mybatis之高级结果映射

    先贴一句官方文档内容 如果世界总是这么简单就好了. 正如官方文档所说:如果一切都是这么简单,那该多好啊,但是实际上,我们面对的是复杂的对象,就是对象里有对象,有列表对象,总之五花八门的对象.这个时候我 ...

随机推荐

  1. redis主从+哨兵 安装配置二

    实验环境: 192.168.2.201 centos7 master sentinel 192.168.2.202 centos7 slave   sentinel 192.168.2.203 cen ...

  2. 【python爬虫】 爬云音乐我和xxx共同听过的歌曲

    闲聊的时候,觉得,想写个爬虫,爬下2个人共同听过的歌曲有哪些,然后一鼓作气,花了一个多小时,写了一个.支持最近一周和所有时间,需要用户没有关闭听歌排行显示 How to start 使用到的工具是Se ...

  3. 解决Spring对静态变量无法注入问题(转)

    问题今天在学习的过程中想写一个连接和线程绑定的JDBCUtils工具类,但测试时发现一直报空指针异常,上网查了之后Spring并不支持对静态成员变量注入,所以光试用@Autowired肯定是不行的.可 ...

  4. POI读取格式化后的单元格数据

    public static String getFormattedValue(Cell cell) { FormulaEvaluator evaluator = cell.getSheet().get ...

  5. C++自定义方法类、调用

    如求矩形.圆的面积的方法,可以写成一个area类 area.h中只声明,不实现: #ifndef AREA_H //防止重复引用 #define AREA_H class area{//自定义类 pu ...

  6. 010_linuxC++之_运算符重载

    (一)运算符重载:运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型. (二)实现类不同对象里中变量的相加 (三)程序 #include <iostream> ...

  7. Task , Thread 学习

    1.任务StartNew后就开始执行,使用Wait()来确保任务结束后继续 static void Main(string[] args) { try { int numberOfUsers = 10 ...

  8. 微信小程序开发入门教程(四)---自己动手做个小程序

    前面已将基础知识准备的差不多了,下面实际做一个小程序. 一.目标 用于上传照片和文字. 2个主要页面:我me,设置set 二.开始制作 1.打开微信开发者工具(我用的1.02.1907160 Wind ...

  9. 二维DFT

    学习DIP第4天 傅里叶变换数学原理会在后续完整介绍,目前只实现代码,观察下结果,公式在上一篇博客中已经描述 内容迁移至 http://www.face2ai.com/DIP-2-2-二维DFT/ h ...

  10. Centos 7 搭建蓝鲸V4.1.16稳定社区版

    在本地用VMware模拟了三台主机 准备至少3台 CentOS 7 以上操作系统的机器,保证三台虚拟机都可以上网 最低配置:2核4G(我用的是这个) 建议配置: 4核12G 以上 192.168.16 ...