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();
}
本文来自博客园,作者:Javaer1995,转载请注明原文链接:https://www.cnblogs.com/Javaer1995/p/17459409.html