本文以 SpringBoot 整合 Mybatis
为例,讲解项目中一对多和多对一的简单用法
@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;
}
@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;
}
# 数据库连接
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
@Configuration // 将它标注的类为配置类
@MapperScan("com.cy.mybatis.mapper")
public class MybatisConfig {
}
public interface EmpMapper {
// 根据员工id查询员工信息(包括部门信息)
Map<String,Object> getObjectByIdToMap(@Param("eid") int eid);
// 根据员工id查询员工信息(包括部门信息)
Emp getEmpAndDeptById(@Param("eid") int eid);
}
public interface DeptMapper {
// 通过部门id查询部门所有信息(包含部门员工)
Dept getDeptAndEmpById(@Param("did") int did);
}
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>
测试输出结果:
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" 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>
步骤一:EmpMapper.java
public interface EmpMapper {
/**
* 通过分布查询: 查询员工以及员工所对应的部门信息
* 分布查询第一步: 查询员工信息
* @param eid 员工id
* @return
*/
Emp getEmpAndDeptByIdStepOne(@Param("eid") int eid);
}
步骤二:EmpMapper.xml
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
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语句
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="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>
@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() 测试方法输出结果
@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
结果集映射 添加
标签
property
需要处理多对一的映射关系的属性名称 如:Dept dept 中的dept
javaType
该属性的类型 如:Dept dept 中的Dept
Emp
)添加多的类型的属性的集合 (List emps
)ResultMap
结果集映射 添加
标签
property
需要处理一对多的映射关系的属性名称 如:List emps 中的emps
ofType(的类型)
该属性所对应的集合中存储的类型,集合中泛型的类型 如:List emps 中的Emp