前言
本文以 SpringBoot 整合 Mybatis
为例,讲解项目中一对多和多对一的简单用法
项目结构
一、数据库表
1. 员工表 t_emp
2. 部门表 t_dept
二、实体类
1. Emp 员工实体类(添加多对一属性)
@Data
public class Emp {
private Integer eId;
private String eName;
private Integer age;
private String sex;
private String phone;
private String email;
// 多对一关系 后添加的属性
private Dept dept;
}
2. dept 部门实体类(添加一对多属性)
@Data
public class Dept {
private Integer dId;
private String dName;
private String dLocation;
// private Emp emp1;
// private Emp emp2;
// private Emp emp3;
// ... 可能出来0 ~ ? Emp对象 一对多关系 后添加的属性
private List<Emp> emps;
}
三、配置文件,配置类
1. 配置文件 application.properties
# 数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai
# 数据库用户名
spring.datasource.username=root
# 数据库密码
spring.datasource.password=root
# 关联映射的配置(指定XML文件所在的位置)
mybatis.mapper-locations=classpath:mappers/*.xml
# 配置别名
mybatis.type-aliases-package=com.cy.mybatis.pojo.entity
# 开启驼峰映射
mybatis.configuration.map-underscore-to-camel-case=true
# 日志
logging.level.com.cy.mybatis.mapper=debug
2. 配置类 MybatisConfig.java
@Configuration // 将它标注的类为配置类
@MapperScan("com.cy.mybatis.mapper")
public class MybatisConfig {
}
四、持久层接口
1. EmpMapper.java
public interface EmpMapper {
// 根据员工id查询员工信息(包括部门信息)
Map<String,Object> getObjectByIdToMap(@Param("eid") int eid);
// 根据员工id查询员工信息(包括部门信息)
Emp getEmpAndDeptById(@Param("eid") int eid);
}
2. DeptMapper.java
public interface DeptMapper {
// 通过部门id查询部门所有信息(包含部门员工)
Dept getDeptAndEmpById(@Param("did") int did);
}
五、xml映射文件
1. EmpMapper.xml(多对一)
1.1 级联
<?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="com.cy.mybatis.mapper.EmpMapper">
<!-- 自定义映射关系 -->
<resultMap id="empAndDeptResultMap" type="emp">
<id column="e_id" property="eId"/>
<result column="e_name" property="eName"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<result column="phone" property="phone"/>
<result column="email" property="email"/>
<!-- 级联查询自定义映射关系 -->
<result column="d_id" property="dept.dId"/>
<result column="d_name" property="dept.dName"></result>
<result column="d_location" property="dept.dLocation"></result>
</resultMap>
<select id="getEmpAndDeptById" resultMap="empAndDeptResultMap">
select *
from t_emp e
join t_dept d
on e.d_id=d.d_id
where e.e_id = #{eid}
</select>
</mapper>
测试输出结果:
1.2 association 标签 – 关联查询(常用)
<?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="com.cy.mybatis.mapper.EmpMapper">
<-- 通过Map封装查询结果 -->
<select id="getObjectByIdToMap" resultType="java.util.Map">
select *
from t_emp e
join t_dept d
on e.d_id=d.d_id
where e.e_id = #{eid}
</select>
<!-- 自定义映射关系 -->
<resultMap id="empAndDeptResultMap" type="emp">
<id column="e_id" property="eId"/>
<result column="e_name" property="eName"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<result column="phone" property="phone"/>
<result column="email" property="email"/>
<!--
association: 处理多对一的映射关系
参数: property 需要处理多对一的映射关系的属性名称 Dept dept 中的dept
javaType(java类型) 该属性的类型 Dept dept 中的Dept
-->
<association property="dept" javaType="Dept">
<id column="d_id" property="dId"></id>
<result column="d_name" property="dName"></result>
<result column="d_location" property="dLocation"></result>
</association>
</resultMap>
<select id="getEmpAndDeptById" resultMap="empAndDeptResultMap">
select *
from t_emp e
join t_dept d
on e.d_id=d.d_id
where e.e_id = #{eid}
</select>
</mapper>
1.3 association 标签 – 分布查询(更常用)
-
步骤一:
EmpMapper.java
public interface EmpMapper { /** * 通过分布查询: 查询员工以及员工所对应的部门信息 * 分布查询第一步: 查询员工信息 * @param eid 员工id * @return */ Emp getEmpAndDeptByIdStepOne(@Param("eid") int eid); }
-
步骤二:
EmpMapper.xml
<?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="com.cy.mybatis.mapper.EmpMapper"> <resultMap id="EmpAndDeptByIdStepResultMap" type="emp"> <id column="e_id" property="eId"/> <result column="e_name" property="eName"/> <result column="age" property="age"/> <result column="sex" property="sex"/> <result column="phone" property="phone"/> <result column="email" property="email"/> <-- association: 处理多对一的映射关系 参数: property 需要处理多对一的映射关系的属性名称 Dept dept 中的dept select 设置分部查询的sql语句的唯一标识(namespace.SQLId或mapper接口的全限定名.方法名) column 设置分部查询的条件(第二步查询需要的条件) --> <association property="dept" select="com.cy.mybatis.mapper.DeptMapper.getEmpAndDeptByIdStepTwo" column="d_id"></association> </resultMap> <select id="getEmpAndDeptByIdStepOne" resultMap="EmpAndDeptByIdStepResultMap"> select * from t_emp where e_id = #{eid} </select> </mapper>
-
步骤三:
DeptMapper.java
public interface DeptMapper { /** * 通过分布查询: 查询员工以及员工所对应的部门信息 * 分布查询第二步: 通过did查询员工所对应的部门信息 * @param did 部门id * @return */ Dept getEmpAndDeptByIdStepTwo(@Param("did") int did); }
-
步骤四:
DeptMapper.xml
<?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="com.cy.mybatis.mapper.DeptMapper"> <resultMap id="DeptResultMap" type="dept"> <id column="d_id" property="dId"/> <result column="d_name" property="dName"/> <result column="d_location" property="dLocation"/> </resultMap> <select id="getEmpAndDeptByIdStepTwo" resultMap="DeptResultMap"> select * from t_dept where d_id = #{did} </select> </mapper>
-
步骤五:测试类测试
EmpMapperTests.java
@SpringBootTest public class EmpMapperTests { @Autowired EmpMapper empMapper; @Test void testGetEmpAndDeptByIdStepOne() { Emp emp = empMapper.getEmpAndDeptByIdStepOne(1); System.out.println(emp); } }
测试结果:
与之前的关联查询不同,这里执行的是两条SQL语句
2. DeptMapper.xml(一对多)
2.1 collection 标签 – 关联查询(常用)
<?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="com.cy.mybatis.mapper.DeptMapper">
<!--
collection: 处理一对多的映射关系
参数: property 需要处理一对多的映射关系的属性名称 List<Emp> emps 中的emps
ofType(的类型) 该属性所对应的集合中存储的类型,集合中泛型的类型 List<Emp> emps 中的Emp
-->
<resultMap id="DeptAndEmpBResultMap" type="dept">
<id column="d_id" property="dId"/>
<result column="d_name" property="dName"/>
<result column="d_location" property="dLocation"/>
<collection property="emps" ofType="Emp">
<id column="e_id" property="eId"/>
<result column="e_name" property="eName"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<result column="phone" property="phone"/>
<result column="email" property="email"/>
</collection>
</resultMap>
<select id="getDeptAndEmpById" resultMap="DeptAndEmpBResultMap">
select *
from t_emp
join t_dept
on t_emp.d_id=t_dept.d_id
where t_dept.d_id = #{did}
</select>
</mapper>
2.2 collection 标签 – 分步查询(更常用)
- 持续更新…
六、测试类
1. EmpMapperTests
@SpringBootTest
public class EmpMapperTests {
@Autowired
EmpMapper empMapper;
@Test
void testGetObjectByIdToMap() {
Map<String, Object> map = empMapper.getObjectByIdToMap(1);
System.out.println(map);
}
@Test
void testGetEmpAndDeptById() {
Emp emp = empMapper.getEmpAndDeptById(1);
System.out.println(emp);
}
}
输出结果
testGetObjectByIdToMap() 测试方法输出结果
testGetEmpAndDeptById() 测试方法输出结果
2. DeptMapperTests
@SpringBootTest
public class DeptMapperTests {
@Autowired
DeptMapper deptMapper;
@Test
void testGetDeptAndEmpById() {
Dept dept = deptMapper.getDeptAndEmpById(1);
System.out.println(dept);
}
}
输出结果
总结
在处理这种一对多和多对一映射关系的业务中,我们可以通过两种方式去实现:
- 封装到
Map
容器中 - 添加自定义映射关系
ResultMap
- 多对一
- 实体类
- 在多的那个实体类中(
Emp
)添加一的类型的属性 (Dept dept
)
- 在多的那个实体类中(
ResultMap
结果集映射 添加<association>
标签- 属性
property
需要处理多对一的映射关系的属性名称 如:Dept dept 中的dept
javaType
该属性的类型 如:Dept dept 中的Dept
- 属性
- 实体类
- 一对多
- 实体类
- 在一的那个实体类中(
Emp
)添加多的类型的属性的集合 (List<Emp> emps
)
- 在一的那个实体类中(
ResultMap
结果集映射 添加<collection>
标签- 属性
property
需要处理一对多的映射关系的属性名称 如:List<Emp> emps 中的emps
ofType(的类型)
该属性所对应的集合中存储的类型,集合中泛型的类型 如:List<Emp> emps 中的Emp
- 属性
- 实体类
- 多对一
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/107601.html