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 ,对面向对象的支持也是很完备的.这 ...
随机推荐
- 2022-03-23:在k进制下,最小多小的num,可以让1~num范围的数拥有1的个数不少于n个? 腾讯音乐2022校园招聘。
2022-03-23:在k进制下,最小多小的num,可以让1~num范围的数拥有1的个数不少于n个? 腾讯音乐2022校园招聘. 答案2022-03-23: 二分法. 代码用golang编写.代码如下 ...
- 解决:Invalid HTTP_HOST header: '192.168.56.1:8001'. You may need to add '192.168.56.1' to ALLOWED_HOSTS.
在setting.py下的ALLOWED_HOSTS=['*']添加'*'就可以解决显示不出来的问题.
- Burpsuite抓包工具的使用
一.打开工具 1处箭头为 代理127.0.0.1 端口8080 2处箭头为 证书 将证书ca下载到桌面上 选择第一个 选择下载到桌面即可 可以修改其后缀为der 此即为证书文件 此处使用火狐浏览器为示 ...
- 谷歌语法Github及利用方式
0x01简介 GoogleHack(谷歌语法)是指使用Google等搜索引擎对某些特定的网络主机漏洞(通常是服务器上的脚本漏洞)进行搜索,以达到快速找到漏洞主机或特定主机的漏洞的目的.比如使用搜索包含 ...
- 多线程的未捕获异常类 UncaughtExceptionHandler 的使用
一.需要 UncaughtExceptionHandler 的原因 1. 主线程可轻松的发现异常,子线程的异常比较隐蔽,难以发现 程序运行时,子线程发生了异常,并不影响主线程,也不会终止主线程的程序, ...
- 包含引用类型字段的自定义结构体,能作为map的key吗
1. 引言 在 Go 语言中,map是一种内置的数据类型,它提供了一种高效的方式来存储和检索数据.map是一种无序的键值对集合,其中每个键与一个值相关联.使用 map 数据结构可以快速地根据键找到对应 ...
- R EnhancedVolcano 绘制火山图
火山图是用于差异表达分析结果可视化的一种有效方法.今天,我们来介绍一个用于增强火山图绘制的强大 R 包:EnhancedVolcano ,该包拥有强大的绘图功能,用户可以简单的通过设置颜色.形状.大小 ...
- 「AntV」X6开发实践:踩过的坑与解决方案
长期更新版文档请移步语雀(「AntV」X6开发实践:踩过的坑与解决方案 (yuque.com)) ️ | 如何自定义拖拽源? 相信你们在开发中更多的需求是需要自定义拖拽源,毕竟自定义的功能扩展性高一些 ...
- Vue——动态组件、插槽、Vue-cli创建项目、Vue项目目录结构、编写规范、es6导入导出语法
动态组件 // <component :is="who"></component> // component标签的is属性等于组件名字,这里就会显示这个组件 ...
- Terraform 改善基础架构的十个最佳实践
Terraform 是一种非常流行的开源 IaC(基础设施即代码)工具,用于定义和提供完整的基础设施.Terraform 于 2014 年推出,其采用率已在全球范围内快速增长,越来越多的开发人员正在学 ...