8.1、环境搭建

8.1.1、创建新module

创建名为mybatis_resultMap的新module,过程参考5.1节

8.1.2、创建t_emp和t_dept表

CREATE TABLE `t_emp` (
`emp_id` int(11) NOT NULL AUTO_INCREMENT,
`emp_name` varchar(20) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`gender` char(1) DEFAULT NULL,
`dept_id` varchar(100) DEFAULT NULL,
PRIMARY KEY (`emp_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

CREATE TABLE `t_dept` (
`dept_id` int(11) NOT NULL AUTO_INCREMENT,
`dept_name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`dept_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

8.1.3、创建Emp实体类

package org.rain.mybatis.pojo;

/**
* @author liaojy
* @date 2023/6/7 - 0:11
*/
public class Emp {
private Integer empId;
private String empName;
private Integer age;
private String gender; public Emp() {
} public Emp(Integer empId, String empName, Integer age, String gender) {
this.empId = empId;
this.empName = empName;
this.age = age;
this.gender = gender;
} public Integer getEmpId() {
return empId;
} public void setEmpId(Integer empId) {
this.empId = empId;
} public String getEmpName() {
return empName;
} public void setEmpName(String empName) {
this.empName = empName;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public String getGender() {
return gender;
} public void setGender(String gender) {
this.gender = gender;
} @Override
public String toString() {
return "Emp{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}

8.1.4、创建Dept实体类

package org.rain.mybatis.pojo;

/**
* @author liaojy
* @date 2023/6/7 - 0:17
*/
public class Dept { private Integer deptId;
private String deptName; public Dept() {
} public Dept(Integer deptId, String deptName) {
this.deptId = deptId;
this.deptName = deptName;
} public Integer getDeptId() {
return deptId;
} public void setDeptId(Integer deptId) {
this.deptId = deptId;
} public String getDeptName() {
return deptName;
} public void setDeptName(String deptName) {
this.deptName = deptName;
} @Override
public String toString() {
return "Dept{" +
"deptId=" + deptId +
", deptName='" + deptName + '\'' +
'}';
}
}

8.1.5、创建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="org.rain.mybatis.mapper.EmpMapper"> </mapper>

8.1.6、创建测试类

8.2、字段和属性的映射关系

8.2.1、接口方法

Emp getEmpByEmpId(@Param("empId") Integer empId);

8.2.2、映射文件

    <!--Emp getEmpByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpByEmpId" resultType="Emp">
select * from t_emp where emp_id = #{empId}
</select>

8.2.3、测试方法

    @Test
public void testGetEmpByEmpId(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = empMapper.getEmpByEmpId(1);
System.out.println(emp);
sqlSession.close();
}

8.2.4、执行效果

注意:与字段名不匹配的属性值为null

8.2.5、映射文件纠正

8.2.5.1、方式一:设置别名

    <!--Emp getEmpByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpByEmpId" resultType="Emp">
<!-- select * from t_emp where emp_id = #{empId} -->
select emp_id empId ,emp_name empName,age,gender from t_emp where emp_id = #{empId}
</select>

8.2.5.1、方式二:使用自定义映射

    <!--
resultMap标签:设置自定义映射
id属性:表示自定义映射的唯一标识
type属性:查询的数据要映射的实体类类型 子标签:
id:设置主键的映射关系
result:设置普通字段的映射关系
子标签属性:
property:设置映射关系中实体类的属性名
column:设置映射关系中表的字段名
-->
<resultMap id="empResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
</resultMap> <!--Emp getEmpByEmpId(@Param("empId") Integer empId);-->
<!--
resultMap属性:设置要使用的自定义映射
-->
<select id="getEmpByEmpId" resultMap="empResultMap">
select * from t_emp where emp_id = #{empId}
</select>

8.3、多对一映射关系

8.3.1、实体类调整

注意:在多(员工)对一(部门)关系中,(员工)实体类有一个(部门)对象

package org.rain.mybatis.pojo;

/**
* @author liaojy
* @date 2023/6/7 - 0:11
*/
public class Emp { private Integer empId;
private String empName;
private Integer age;
private String gender; private Dept dept; public Emp() {
} public Emp(Integer empId, String empName, Integer age, String gender) {
this.empId = empId;
this.empName = empName;
this.age = age;
this.gender = gender;
} public Integer getEmpId() {
return empId;
} public void setEmpId(Integer empId) {
this.empId = empId;
} public String getEmpName() {
return empName;
} public void setEmpName(String empName) {
this.empName = empName;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public String getGender() {
return gender;
} public void setGender(String gender) {
this.gender = gender;
} public Dept getDept() {
return dept;
} public void setDept(Dept dept) {
this.dept = dept;
} @Override
public String toString() {
return "Emp{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", dept=" + dept +
'}';
}
}

8.3.2、接口方法

Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);

8.3.3.、测试方法

    @Test
public void testGetEmpAndDeptByEmpId(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = empMapper.getEmpAndDeptByEmpId(1);
System.out.println(emp);
sqlSession.close();
}

8.3.4、映射文件

8.3.4.1、方式一:级联

注意:字段不能匹配对象,只能匹配对象中的属性;因此使用级联方式时,property值的形式为:对象名.属性名

    <resultMap id="empAndDeptResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<result column="dept_id" property="dept.deptId"></result>
<result column="dept_name" property="dept.deptName"></result>
</resultMap> <!--Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">
select * from t_emp left join t_dept on t_emp.dept_id = t_dept.dept_id where emp_id = #{empId}
</select>

8.3.4.2、方式二:association标签

比起级联方式,使用association标签的层次更加分明

    <resultMap id="empAndDeptResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!--
association标签:设置多对一的映射关系,用于处理实体类类型的属性
property属性:设置要处理的实体类属性名
javaType属性:设置要处理的实体类属性的类型(此处和resultType一样可以使用实体类类型别名)
-->
<association property="dept" javaType="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
</association>
</resultMap> <!--Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">
select * from t_emp left join t_dept on t_emp.dept_id = t_dept.dept_id where emp_id = #{empId}
</select>

8.4、一对多映射关系

8.4.1、实体类调整

注意:在一(部门)对多(员工)关系中,(部门)实体类有一个(员工)对象集合

package org.rain.mybatis.pojo;

import java.util.List;

/**
* @author liaojy
* @date 2023/6/7 - 0:17
*/
public class Dept { private Integer deptId;
private String deptName; private List<Emp> emps; public Dept() {
} public Dept(Integer deptId, String deptName) {
this.deptId = deptId;
this.deptName = deptName;
} public Integer getDeptId() {
return deptId;
} public void setDeptId(Integer deptId) {
this.deptId = deptId;
} public String getDeptName() {
return deptName;
} public void setDeptName(String deptName) {
this.deptName = deptName;
} public List<Emp> getEmps() {
return emps;
} public void setEmps(List<Emp> emps) {
this.emps = emps;
} @Override
public String toString() {
return "Dept{" +
"deptId=" + deptId +
", deptName='" + deptName + '\'' +
", emps=" + emps +
'}';
}
}

8.4.2、接口方法

Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);

8.4.3、测试方法

    @Test
public void testGetDeptAndEmpByDeptId(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = deptMapper.getDeptAndEmpByDeptId(1);
System.out.println(dept);
sqlSession.close();
}

8.4.4、映射文件

注意:一对多映射关系,不能使用级联的方式处理

    <resultMap id="deptAndEmpResultMap" type="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<!--
collection标签:设置一对多映射关系,用于处理集合类型的属性
property属性:设置要处理的集合类型属性名
ofType属性:设置要处理的集合类型属性中存储的(实体类)数据类型
-->
<collection property="emps" ofType="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
</collection>
</resultMap> <!--Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);-->
<select id="getDeptAndEmpByDeptId" resultMap="deptAndEmpResultMap">
select * from t_dept left join t_emp on t_dept.dept_id = t_emp.dept_id where t_dept.dept_id = #{deptId}
</select>

8.5、分步查询与延迟加载

8.5.1、多对一的分步查询

8.5.1.1、接口方法

Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);

+++++++++++++++++++++++分割线+++++++++++++++++++++++

注意:返回类型,和要查询的属性类型一致。

Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId);

8.5.1.2、映射文件

    <!--Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId);-->
<select id="getEmpAndDeptByStepTwo" resultType="Dept">
select * from t_dept where dept_id = #{deptId}
</select>

+++++++++++++++++++++++分割线+++++++++++++++++++++++

    <resultMap id="empAndDeptBySetpResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!--
property属性:设置要处理的实体类属性名
select属性:设置分布查询的SQL的唯一标识,用于查询实体类属性的值
column属性:设置某个字段作为分布查询的SQL的条件
-->
<association property="dept" select="org.rain.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo" column="dept_id">
</association>
</resultMap> <!--Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptBySetpResultMap">
select * from t_emp where emp_id = #{empId}
</select>

8.5.1.3、核心配置文件

注意:该全局配置是为了简化手动映射下划线和驼峰的关系;当已使用resultMap手动映射下划线和驼峰的关系,则可以不使用该全局配置

    <settings>
<!--将下划线映射为驼峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

8.5.1.4、测试方法

    @Test
public void testGetEmpAndDeptByStep(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = empMapper.getEmpAndDeptByStepOne(1);
System.out.println(emp);
sqlSession.close();
}

8.5.1.5、执行效果

由控制台日志可知,该分步查询执行了两次SQL

8.5.2、延迟加载

8.5.2.1、核心配置文件

注意:开启延迟加载的前提是aggressiveLazyLoading的全局配置值为false,即<setting name="lazyLoadingEnabled" value="false"/>

由于Mybatis 3.4.1之后版本的aggressiveLazyLoading默认值就是false,所以可省略

    <settings>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>

8.5.2.2、执行效果

注意:分步查询的优点是可以实现延迟加载;由控制台日志可知,当第一步的查询SQL满足需要时,第二步的查询SQL不会执行

8.5.2.3、局部配置延迟加载

    <resultMap id="empAndDeptBySetpResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!--
fetchType属性:设置当前的分步查询是否使用延迟加载;eager为立即加载,lazy为延迟加载
-->
<association property="dept" fetchType="lazy"
select="org.rain.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo" column="dept_id">
</association>
</resultMap>

8.5.3、一对多的分步查询

8.5.3.1、接口方法

Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);

+++++++++++++++++++++++分割线+++++++++++++++++++++++

注意:返回类型,和要查询的属性类型一致。

List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);

8.5.3.2、映射文件

    <!--List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);-->
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
select * from t_emp where dept_id = #{deptId}
</select>

+++++++++++++++++++++++分割线+++++++++++++++++++++++

    <resultMap id="deptAndEmpByStepResultMap" type="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<collection property="emps" select="org.rain.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo" column="dept_id">
</collection>
</resultMap> <!--Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);-->
<select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpByStepResultMap">
select * from t_dept where dept_id = #{deptId}
</select>

8.5.3.3、测试方法

    @Test
public void testGetDeptAndEmpByStep(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = deptMapper.getDeptAndEmpByStepOne(1);
System.out.println(dept);
sqlSession.close();
}

8、Mybatis之自定义映射的更多相关文章

  1. mybatis:自定义映射关系resultMap

    创建表t_emp 定义实体类 package org.example.entity; public class Emp { private Integer empId; private String ...

  2. Mybatis中自定义映射xml参数传递使用

    在使用mybatis框架时,大多时候自动生成的mapper.xml文件能满足我们所需的数据库操作,但一些情况下还是需要我们自己写sql:为了加深印象,总结了下参数传递的方式以及各个关键字的含义如下: ...

  3. MyBatis的类型自定义映射

    背景 利用MyBatis将数据库的时间类型映射成Java8的时间类型,引申对不同类型的自定义映射 实现方法 1.实现MyBatis中TypeHandler接口 @MappedTypes(value = ...

  4. MyBatis实战之映射器

    映射器是MyBatis最强大的工具,也是我们使用MyBatis时用得最多的工具,因此熟练掌握它十分必要.MyBatis是针对映射器构造的SQL构建的轻量级框架,并且通过配置生成对应的JavaBean返 ...

  5. Mybatis(二) SQL映射文件

    SQL映射文件 单条件查询 1. 在UserMapper接口添加抽象方法 //根据用户名模糊查询 List<User> getUserListByName(); 2. 在UserMappe ...

  6. Mybatis系列全解(五):全网最全!详解Mybatis的Mapper映射文件

    封面:洛小汐 作者:潘潘 若不是生活所迫,谁愿意背负一身才华. 前言 上节我们介绍了 < Mybatis系列全解(四):全网最全!Mybatis配置文件 XML 全貌详解 >,内容很详细( ...

  7. MyBatis_06(自定义映射resultMap)

    主题:自定义映射resultMap "自定义映射resultMap",可以解决什么问题: 1-"属性" 和 "字段名" 不一致的情况 2-& ...

  8. 5.Mybatis的输出映射(就是对查询的结果集的映射)

    Mybatis的输出映射,也就是对查询结果集的一个映射,主要有两种: 1.resultType(不需要配置,可以直接用) 一般是实体类 基本类型也可以 2.resultMap(需要配置resultMa ...

  9. MyBatis Generator 自定义生成注释

    注释生成器 为了生成db里面的注释,必须自定义注释生成器 EmptyCommentGenerator: import org.mybatis.generator.api.CommentGenerato ...

  10. mybatis 根据参数映射对应模型

    ORM 框架的优势在于能让我们利用面向对象的思维去操作数据库, hibernate 作为重量级的 ORM 框架对面向对象的支持很强大.作为半自动化的 mybatis ,对面向对象的支持也是很完备的.这 ...

随机推荐

  1. vue全家桶进阶之路20:ECMAScript脚本语言规范

    ECMAScript(简称 ES)是一种由 Ecma 国际组织定义的脚本语言标准,它定义了 JavaScript 语言的基本规范和特性.JavaScript 是一种基于 ECMAScript 标准的编 ...

  2. 如何在Docker Compose中限制容器的CPU和内存使用?

    最近我在使用开源统计Umami过程中,发现CPU和内存经常占满,导致其它服务都不能正常使用.Umami我使用的docker-compose进行部署,于是打算使用docker-compose限制下容器的 ...

  3. python -- pandas常见的一些行、列操作方法(感兴趣的,可以跟着一起练练手)

    这篇文章分享一下pandas常见的一些行.列操作方法,比较基础,感兴趣的童鞋可以看看. 首先,我们用 "random.seed(int i)" 生成一组测试数据. 对于random ...

  4. Doris(五) -- 数据的导入导出

    数据导入 使用 Insert 方式同步数据 用户可以通过 MySQL 协议,使用 INSERT 语句进行数据导入 INSERT 语句的使用方式和 MySQL 等数据库中 INSERT 语句的使用方式类 ...

  5. 曲线艺术编程 coding curves 第五章 谐波图形(谐振图形) HARMONOGRAPHS

    原作:Keith Peters https://www.bit-101.com/blog/2022/11/coding-curves/ 译者:池中物王二狗(sheldon) blog: http:// ...

  6. Python的Lambda函数: 一把极简编程的瑞士军刀

    Python中的lambda函数,或者叫匿名函数,是一个极其强大的工具.它以简洁.优雅的语法提供了创建函数的快速方式.在本篇文章中,我们将全方位地深入研究lambda函数的用法和特点,通过理论和实例相 ...

  7. [汽车]车架号(VIN)的设计与规范

    1 车架号概述 VIN是英文Vehicle Identification Number(车辆识别代码)的缩写,也就是我们平时所说的车架号.大架号. 总共由17位字符组成,是汽车唯一的身份识别信息,好比 ...

  8. 分布式数据库 Join 查询设计与实现浅析

    相对于单例数据库的查询操作,分布式数据查询会有很多技术难题. 本文记录 Mysql 分库分表 和 Elasticsearch Join 查询的实现思路,了解分布式场景数据处理的设计方案. 文章从常用的 ...

  9. Instruments中常用Template的使用

     Instruments是苹果提供的Xcode套件,可用于分析iOS,MacOS程序的性能数据,进行性能提升.Instruments提供了很多类型的Template,用于特定场景的分析.这里选了3种常 ...

  10. AGC019F Yes or No

    题意 有 \(N+M\) 个问题,其中有 \(N\) 个问题的答案是 YES,\(M\) 个问题的答案是 NO.当你回答一个问题之后,会知道这个问题的答案,求最优策略下期望对多少.答案对 \(9982 ...