目录
前言
自定义映射resultMap标签
resultType标签
准备sql表
多对一映射处理
1、级联方式处理映射关系
2、使用association处理映射关系
3、分步查询
①查询员工信息
②根据员工所对应的部门id查询部门信息
一对多映射处理
1、collenction
2、分步查询
①查询部门信息
②根据部门id查询部门中的所有员工
association和 collection
前言
MyBatis是一种持久层框架,用于简化数据库操作。在MyBatis中,映射是指将数据库中的数据映射到Java对象中的过程,而resultMap标签则用于定义映射规则。
resultMap标签是MyBatis中用于定义结果集映射规则的标签。它可以指定如何将查询结果映射到Java对象中的属性,包括列名和Java属性名的映射关系,以及复杂类型的映射规则。
一对多映射指的是一个Java对象中包含多个子对象的映射关系。在MyBatis中,可以使用collection标签来定义一对多映射的规则,指定父对象和子对象之间的映射关系,以及如何将查询结果映射到Java对象中。
多对一映射指的是多个Java对象中包含一个共同的父对象的映射关系。在MyBatis中,可以使用association标签来定义多对一映射的规则,指定子对象和父对象之间的映射关系,以及如何将查询结果映射到Java对象中。
自定义映射resultMap标签
resultMap是MyBatis中最强大的结果映射方式,它允许你自定义复杂的数据结构映射规则。当查询结果与实体类属性名不匹配或者需要处理关联关系时,可以使用此标签。resultMap会详细描述数据库表字段到Java对象属性之间的映射,以及嵌套结果集的映射。
若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射
resultMap:设置自定义映射属性,包含有以下几个标签:
id:表示自定义映射的唯一标识
type:查询的数据要映射的实体类的类型子标签:
id:设置主键的映射关系
result:设置普通字段的映射关系
association:设置多对一的映射关系
collection:设置一对多的映射关系属性
property:设置映射关系中实体类中的属性名
column:设置映射关系中表中的字段名
resultType标签
相对于resultMap,resultType标签提供了更为简洁的结果映射方式。它直接指定一个类型(通常是一个Java Bean的全限定类名),MyBatis会按照默认规则将查询结果中的列名自动映射到Java对象具有相同名称的属性上。
准备sql表
两张表,部门表和员工表,字段如下:
名 |
类型 |
备注 |
id |
int |
主键 |
name |
vachar |
部门名称 |
名 |
类型 |
备注 |
id |
int |
主键 |
name |
vachar |
员工姓名 |
gender |
vachar |
性别 |
salary |
double |
薪资 |
join_date |
date |
入职日期 |
dept_id |
int |
外键 |
bean
@Data @AllArgsConstructor @NoArgsConstructor public class Dept { private Integer id; private String name; private List<Emp> empList; }
@Data @AllArgsConstructor @NoArgsConstructor public class Emp { private Integer id; private String name; private String gender; private Double salary; private Date joinDate; private Integer deptId; //一对一关系 private Dept dept; //引入Dept类 }
多对一映射处理
场景模拟:
查询员工信息以及员工所对应的部门信息
已知员工是多,部门是一,一个员工对应多个部门,一个部门有多个员工。两种方式处理映射关系
1、级联方式处理映射关系
级联方式:
<!--多对一映射关系,,级联关系查询--> <resultMap id="empDeptMap" type="emp"> <id column="id" property="id"></id> <result column="name" property="name"></result> <result column="gender" property="gender"></result> <result column="salary" property="salary"></result> <result column="join_date" property="joinDate"></result> <result column="dept_id" property="deptId"></result> <result column="dept_id" property="dept.id"></result> <result column="dname" property="dept.name"></result> </resultMap> <!--Emp getEmpAndDeptByEid(@Param("eid") int eid); EmpMapper接口中代码--> <select id="getEmpAndDeptByEid" resultMap="empDeptMap"> select e.*,d.name as dname from emp e left join dept d on e.dept_id = d.id where e.id = #{eid} </select>
2、使用association处理映射关系
<!--定义一个resultMap标签,将Emp字段映射,后面就不用重复去写,需要用到直接继承extends标签即可以--> <resultMap id="baseMap" type="emp"> <id column="id" property="id"></id> <result column="name" property="name"></result> <result column="gender" property="gender"></result> <result column="salary" property="salary"></result> <result column="join_date" property="joinDate"></result> <result column="dept_id" property="deptId"></result> </resultMap> <resultMap id="empDeptMap" type="emp" extends="baseMap"> <association property="dept" javaType="dept"> <id column="id" property="id"></id> <result column="name" property="name"></result> </association> </resultMap> <select id="getEmpAndDeptByEid" resultMap="empDeptMap"> select e.*,d.name as dname from emp e left join dept d on e.dept_id = d.id where e.id = #{eid} </select>
3、分步查询
①查询员工信息
EmpMapper接口
/** *通过分步查询查询员工信息 *@param eid *@return */ Emp getEmpByStep(@Param("eid") int eid);
EmpMapper.xml
分步查询中的association标签用到select属性,就是在调用下一步查询中DeptMapper接口中的一个方法;column属性即是传入的字段。比如根据员工查询部门,我们就得传入员工信息中的部门id--dept_id。
<!-- 多对一 分步查询 查询员工信息--> <resultMap id="empDeptStepMap" type="emp" extends="baseMap"> <association property="dept" select="com.softeem.mapper.DeptMapper.getEmpDeptByStep" column="dept_id"> <!--column一定必须传入的是数据库表的字段名根据什么查就传入什么字段--> <!--select:是在调用某个mapper对象中的某个方法,调用的一定是查询方法--> </association> </resultMap> <select id="getEmpByStep" resultMap="empDeptStepMap"> select * from emp where id = #{eid} </select>
②根据员工所对应的部门id查询部门信息
DeptMapper接口中方法。
/** *分步查询的第二步: 根据员工所对应的did查询部门信息 *@param did *@return */ Dept getEmpDeptByStep(@Param("did") int did);
DeptMapper.xml
<!--Dept getEmpDeptByStep(@Param("did") int did);--> <select id="getEmpDeptByStep" resultType="Dept"> select * from dept where did = #{did} </select>
一对多映射处理
场景模拟:
根据部门id查询部门以及部门中的员工信息
一对多查询时,一那方实体类就要再定义一个集合属性。即部门实体类中还应该再定义List<Emp>。因为查询一个部门,但部门内有多个员工。代码如下:
Dept实体类:
@Data @AllArgsConstructor @NoArgsConstructor public class Dept { private Integer id; private String name; private List<Emp> empList; }
1、collenction
DeptMapper接口中定义方法:
/** *根据部门id查询部门以及部门中的员工信息 *@param did *@return */ Dept getDeptEmpByDid(@Param("did") int did);
DeptMapper.xml映射文件中代码:
<!-- 根据部门id查新部门以及部门中的员工信息 注意点:一对多,在少的bean类写上多的对象集合 在resultMap标签中写上collection标签将多的字段写上,如下,,,值得特别关注的是如果字段名重复记得给别名,否则对应不起来将报错--> <resultMap id="DeptEmpMap" type="dept"> <id property="id" column="did"></id> <result property="name" column="dname" ></result> <!--resultMap标签将EmpMapper.xml中的baseMap标签继承来,就不用再写字段的映射那么些代码了 --> <collection property="empList" ofType="emp" resultMap="com.softeem.mapper.EmpMapper.baseMap"> </collection> </resultMap> <!-- 有重复的一定要写别名--> <select id="getDeptEmpByDid" resultMap="DeptEmpMap"> select e.*, d.id as did, d.name as dname from emp e, dept d where e.dept_id=d.id and d.id=#{did} </select>
注意:两表联查时容易出现表中字段相同的情况,这种情况一定要写别名,并且在resultMap标签中映射
2、分步查询
与上述多对一基本是一致的,只是标签不同,多对一使用的是collection标签
①查询部门信息
DeptMapper接口中方法:
/** *分步查询部门和部门中的员工 *@param did *@return */ Dept getDeptByStep(@Param("did") int did);
DeptMapper.xml文件中代码:
<!-- 一对多映射处理 分步查询 --> <resultMap id="DeptEmpStep" type="dept"> <id property="id" column="id"></id> <result property="name" column="name" ></result> <collection property="empList" select="com.softeem.mapper.EmpMapper.getEmpListByDid" column="id"> </collection> </resultMap> <select id="getDeptByStep" resultMap="DeptEmpStep"> select * from dept where id=#{did} </select>
②根据部门id查询部门中的所有员工
EmpMapper接口中定义方法:
List<Emp> getEmpListByDid(int did);
EmpMapper.xml文件中代码:
<!--List<Emp> getEmpListByDid(@Param("did") int did);--> <select id="getEmpListByDid" resultType="Emp"> select * from t_emp where did = #{did} </select>
association和 collection
在MyBatis中,association 和 collection 是用于处理对象关联关系的标签,它们分别用于实现一对一和一对多(或多对一)的数据映射。
association (一对一或多对一映射)
- 作用:用于描述一个复杂的属性(通常是一个对象),该属性与当前实体类之间是一对一或多对一的关系。
collection (一对多或多对多映射)
- 作用:用于描述一个复杂属性(通常是集合类型,如List、Set等),该属性包含多个与当前实体类有一对多或多对多关系的对象。
总结来说,association 主要用于一对一或者多对一关系,而 collection 适用于处理一对多或者多对多的关系。通过这两种标签,可以方便地将关联表数据映射到Java对象图中,形成一个完整的对象模型。