many2one
案例:员工中有部门属性.
1.查询完员工后,再发查询部门的sql.
在员工的映射文件中,添加属性关系的映射.
<resultMap type="User" id="user_mapping">
<association property="dept" column="dept_id"
select="com.lwf.mybatis.hallo.DeptmentMapper.get"/>
</resultMap>
association标签的属性:
- property: 员工类中的对应属性
- column:查询要用的值(查询的结果表的列)
- javaType: 该属性的java类型
- select: 根据外键查询关联对象的sql的id(写了select可以不写javaType)
此时查询一个员工,并实例化后的结果为发送两条sql.
若查询n个员工(都有部门属性),就会发送1条查员工+n条查部门的sql.(性能太低)
2.内连的映射,(查询员工,同时查询其部门)
在员工的映射文件中,添加属性关系的映射.
- 不用写select属性,但必须写javaType属性
- 由于结果表的列名会重复,所以需要其别名
<resultMap type="User" id="user_mapping">
<association property="dept" column="dept_id" javaType="Deptment">
<id property="id" column="did"/>
<result property="name" column="dname"/>
</association>
</resultMap>
列表查询时候,用left join 部门表格
<select id="list" resultMap="user_mapping">
select
u.id,u.name,u.age,u.birthday,
d.id as did,d.name as dname <!-- 结果表的列 用别名 -->
from user u left join deptment d on u.dept_id=d.id
</select>
此刻查询员工列表对象,只需要一条sql即可.
3.添加/修改操作(只需要改变其sql语句即可,删除直接删)
<!--添加-->
insert into user (name,age,dept_id) values (#{name},#{age},#{dept.id})
<!--修改-->
update employee set name=#{name},age=#{age},dept_id=#{dept.id} where id=#{id}
one2many
案例:部门对象中有员工属性.(外键依然在员工表中)
添加和修改操作
需要添加额外的方法和sql语句,去维护员工表中的员工的dept_id列.
1.mapper中添加方法
//userId,表示一个user对象的id
//deptId,表示一个dept对象的id
void updateRelation(@Param("userId")Long userId, @Param("deptId")Long deptId);
2.映射文件中添加sql
<!-- 维护部门和员工的关系-->
<update id="updateRelation">
update user set dept_id = #{deptId} where id=#{userId}
</update>
3.测试
Deptment dept = new Deptment();
dept.setName("人事部");
dept.getList().add(mapper.get(8L));//给该部门添加两个已经存在的员工
dept.getList().add(mapper.get(9L));
deptmapper.add(dept); //持久化后,自动注入数据库中对应的id值
//维护关系
for (User user : dept.getList()) {
deptmapper.updateRelation(user.getId(),dept.getId());
}
4.小结:
这种方式,较为简单,同时性能低,一个员工发送一条维护关系的sql,
思路2:获取数组对象,放着是该部门的员工的id的数组,mapper的方法形参是部门id+数组对象.映射的sql为:
update user set dept_id = #{deptId} where id in 数组(此处使用遍历)
此时维护关系的代码片段,不再需要遍历
删除操作
依然需要额外的sql去维护二者关系.
void deleteRelation( @Param("deptId")Long deptId);
2.映射文件中添加sql
<!-- 维护部门和员工的关系-->
<update id="deleteRelation">
update user set dept_id = null where id=#{userId}
</update>
3.测试
Deptment dept= mapper.get(1L);
//清空对应员工的外键
for (User user : dept.getList()) {
deptmapper.updateRelation(dept.getId());
}
//删除部门
mapper.delete(1L);
4.小结:
这种方式,较为简单,同时性能低,一个员工发送一条维护关系的sql,
思路2:获取数组对象,放着是该部门的员工的id的数组,mapper的方法形参是数组对象.映射的sql为:
update user set dept_id = null where id in 数组(此处使用遍历)
此时的操作,只需要2步,1:清空外键,2:删除部门(不用遍历)
查询操作
1.查询部门后,再查询对应的员工list(2条sql)
在员工的映射文件中,添加按部门id查询的sql.
<select id="selectByDeptId" resultMap="user_mapping">
select *from user where dept_id=#{id}
</select>
在部门的映射文件中,添加属性关系的映射.
<collection property="list" column="id" ofType="User" select="com.lwf.mybatis.hallo.UserMapper.selectByDeptId"/>
collection标签的属性:
- property: 要映射的属性名
- column : 查询时候要传递的值
- ofType :每一行查询结果的封装
- select :查询的sql位置
2.内连方式(一次查完部门及其员工list)
在部门的映射文件中,添加属性关系的映射.
<!--防止列名冲突,要其别名-->
<collection property="list" ofType="User">
<id property="id" column="uid"/>
<result property="name" column="uname"/>
<result property="age" column="uage"/>
<result property="birthday" column="ubirthday"/>
</collection>
修改查询的sql
<select id="get" parameterType="Long" resultMap="deptment_mapping">
select d.id,d.name,
u.id as uid,u.name as uname, u.age as uage,u.birthday as ubirthday
from deptment d left join user u on d.id=u.dept_id
where d.id=#{id}
</select>
只需要一条sql,就可以查询出对应的部门和员工list.
many2many
案例:部门中有员工list属性,二者关系的多对多.
中间表为 deptment_user.
添加操作
1.需要额外的sql去维护关系
//传递员工的id和部门id,同步到中间表
void addRelation(@Param("userId")Long userId, @Param("deptId")Long deptId);
<!-- 维护中间表-->
<insert id="addRelation">
insert into deptment_user(dept_id,user_id) values(#{deptId},#{userId})
</insert>
2.测试
deptmapper.add(dept);//添加后,就添加其id属性
for (User user : dept.getList()) {
deptmapper.resovleRelation(user.getId(), dept.getId());
}
3.小结
当添加的部门有100个员工,需要100个sql去维护.这个不知道怎么改了...
删除操作
1.删除关系.根据部门id值,将中间表 dept_id=#{id}的行,都删除.
2.删除部门.
修改操作
1.删除关系,根据部门id值,将中间表 dept_id=#{id}的行,都删除.
2.添加关系,即添加部门时候的维护关系的操作.
3.修改部门.
查询操作
1.先查询部门,再查询员工对象
在员工的映射文件中,添加通过部门id,查找员工.
<!--二者关系是在中间表体现的-->
<select id="getByDept" parameterType="Long" resultMap="user_mapping">
select u.id,u.name,u.age,u.birthday
from deptment_user du join user u on du.user_id=u.id
where du.dept_id = #{id}
</select>
在部门的映射文件中,添加属性关系的映射.
<collection property="list" ofType="User" column="id" select="com.lwf.mybatis.hallo.UserMapper.getByDept"/>
3.内连方式.
有中间表的内连方式,拼sql太麻烦~~