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. defer有什么用呢

    1. 简介 本文将从一个资源回收问题引入,引出defer关键字,并对其进行基本介绍.接着,将详细介绍在资源回收.拦截和处理panic等相关场景下defer的使用. 进一步,介绍defer的执行顺序,以 ...

  2. 使用 MRKL 系统跨越神经符号鸿沟

    本文展示了自然语言处理的下一步发展--模块化推理.知识和语言( the Modular Reasoning, Knowledge and Language,简称为MRKL)系统以及LangChain和 ...

  3. 数据库优化案例—某市中心医院HIS系统

    记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例. 最近一直很忙,博客产出也少的 ...

  4. GitLib详细使用手册(windows系统)

    Git是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理. 对gitlab的常见的使用有建立仓库.提交代码.更新代码.回滚代码.显示/修改日志.拉取分支.解决冲突.设置比 ...

  5. 音容笑貌,两臻佳妙,人工智能AI换脸(deepfake)技术复刻《卡萨布兰卡》名场面(Python3.10)

    影史经典<卡萨布兰卡>是大家耳熟能详的传世名作,那一首壮怀激烈,激奋昂扬的马赛曲,应当是通片最为激动人心的经典桥段了,本次我们基于faceswap和so-vits库让AI川普复刻美国演员保 ...

  6. AcWing 3729. 改变数组元素

    给定一个空数组 V 和一个整数数组 a1,a2,-,an. 现在要对数组 V进行 n次操作. 第 i次操作的具体流程如下: 从数组 V尾部插入整数 0.    2.将位于数组 V末尾的 ai 个元素都 ...

  7. Java的Object类的方法

    Java的Object类是所有类的根类,它提供了一些通用的方法.下面是一些常用的Object类方法: 1. equals(Object obj):判断当前对象是否与给定对象相等.默认情况下,equal ...

  8. OCR -- 文本识别 -- 理论篇

    文本识别的应用场景很多,有文档识别.路标识别.车牌识别.工业编号识别等等,根据实际场景可以把文本识别任务分为两个大类:规则文本识别和不规则文本识别. 规则文本识别:主要指印刷字体.扫描文本等,认为文本 ...

  9. FPGA加速技术在游戏和娱乐系统中的应用:实现高效的游戏和娱乐系统

    目录 1. 引言 2. 技术原理及概念 3. 实现步骤与流程 4. 应用示例与代码实现讲解 <35. FPGA加速技术在游戏和娱乐系统中的应用:实现高效的游戏和娱乐系统>这篇文章是一篇针对 ...

  10. Junit4 一直处于运行中的排查过程

    新买了一个Macbook Pro . 之前的工程搬家过来, 这天要跑个单元测试. 发现Junit4 一直处于运行中.没有错误信息,没有用例执行结果.遂开始排查原因. 这里插一句,苹果芯片的Mbp还是很 ...