8、Mybatis之自定义映射
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之自定义映射的更多相关文章
- mybatis:自定义映射关系resultMap
创建表t_emp 定义实体类 package org.example.entity; public class Emp { private Integer empId; private String ...
- Mybatis中自定义映射xml参数传递使用
在使用mybatis框架时,大多时候自动生成的mapper.xml文件能满足我们所需的数据库操作,但一些情况下还是需要我们自己写sql:为了加深印象,总结了下参数传递的方式以及各个关键字的含义如下: ...
- MyBatis的类型自定义映射
背景 利用MyBatis将数据库的时间类型映射成Java8的时间类型,引申对不同类型的自定义映射 实现方法 1.实现MyBatis中TypeHandler接口 @MappedTypes(value = ...
- MyBatis实战之映射器
映射器是MyBatis最强大的工具,也是我们使用MyBatis时用得最多的工具,因此熟练掌握它十分必要.MyBatis是针对映射器构造的SQL构建的轻量级框架,并且通过配置生成对应的JavaBean返 ...
- Mybatis(二) SQL映射文件
SQL映射文件 单条件查询 1. 在UserMapper接口添加抽象方法 //根据用户名模糊查询 List<User> getUserListByName(); 2. 在UserMappe ...
- Mybatis系列全解(五):全网最全!详解Mybatis的Mapper映射文件
封面:洛小汐 作者:潘潘 若不是生活所迫,谁愿意背负一身才华. 前言 上节我们介绍了 < Mybatis系列全解(四):全网最全!Mybatis配置文件 XML 全貌详解 >,内容很详细( ...
- MyBatis_06(自定义映射resultMap)
主题:自定义映射resultMap "自定义映射resultMap",可以解决什么问题: 1-"属性" 和 "字段名" 不一致的情况 2-& ...
- 5.Mybatis的输出映射(就是对查询的结果集的映射)
Mybatis的输出映射,也就是对查询结果集的一个映射,主要有两种: 1.resultType(不需要配置,可以直接用) 一般是实体类 基本类型也可以 2.resultMap(需要配置resultMa ...
- MyBatis Generator 自定义生成注释
注释生成器 为了生成db里面的注释,必须自定义注释生成器 EmptyCommentGenerator: import org.mybatis.generator.api.CommentGenerato ...
- mybatis 根据参数映射对应模型
ORM 框架的优势在于能让我们利用面向对象的思维去操作数据库, hibernate 作为重量级的 ORM 框架对面向对象的支持很强大.作为半自动化的 mybatis ,对面向对象的支持也是很完备的.这 ...
随机推荐
- 2021-11-25:给定两个字符串s1和s2,返回在s1中有多少个子串等于s2。来自美团。
2021-11-25:给定两个字符串s1和s2,返回在s1中有多少个子串等于s2.来自美团. 答案2021-11-25: 改写kmp算法. next数组多求一位. 比如:str2 = aaaa, 那么 ...
- 2021-11-10:O(1) 时间插入、删除和获取随机元素。实现RandomizedSet 类:RandomizedSet() 初始化 RandomizedSet 对象。bool insert(in
2021-11-10:O(1) 时间插入.删除和获取随机元素.实现RandomizedSet 类:RandomizedSet() 初始化 RandomizedSet 对象.bool insert(in ...
- Django-3:创建子项目APP
django-admin startapp app01 或 python manage.py startapp app01 #app01 是app名称 PyCharm的样子:
- Element-DatePicker的宽度
Element如何修改DatePicker的宽度 方法/步骤 1 打开一个vue文件,添加DatePicker日期选择器组件,设置默认日期为null.如图 2 在组件上添加style样式属性,设置wi ...
- blender 3D 建模仿真摄像头视角
前言 摄像头的视角模拟,可以在产品概念设计阶段提供比较直观的视觉效果,通过将模型与实际环境进行校准,基本上可以通过模型来确定摄像头需要FOV,焦距,景深和安装位置及角度等参数. 由于工作需要,第一次自 ...
- Python相关镜像
Python相关镜像 (1) pip使用说明 对于Python开发用户来讲,我们会经常使用pip安装软件包.但国外的源下载速度实在太慢,浪费时间且经常出现下载后安装出错问题.所以把PIP安装源替换成国 ...
- ChatGPT 是否会夺走人们的工作
ChatGPT 是否会夺走人们的工作? 最近,以 ChatGPT 为代表的人工智能项目在自然语言处理这一领域得到了一些突破性的进展,重新引发了人们对于"人工智能会抢走人类工作机会" ...
- 基于 gulp 的 fancybox 源码压缩
前不久,处理生信分析的网页版自动化报告时候就使用过 fancybox,今天在优化个人博客,为博文增加图片缩放效果,解决一些滚动条问题时,才从 fancybox 的 Github 源码中接触到 gulp ...
- IM1281B电能计量模块_C语言例程
一.前言 毕设采用了艾锐达公司的IM1281B电量计能模块,找了一圈没发现具体的51单片机的例程,现在写个能使用的C语言例程,方便以后的开发者们. 二.事前准备 引脚定义: 引脚 功能说明 V+ 供电 ...
- 深度学习中的循环神经网络”在Transformer中的应用
目录 深度学习中的"循环神经网络"在Transformer中的应用 背景介绍 文章目的 目标受众 技术原理及概念 基本概念解释 相关技术比较 实现步骤与流程 准备工作:环境配置与依 ...