【mybatis】【对象属性关系的映射】

本文详细介绍了MyBatis中many2one、one2many和many2many三种对象属性关系的映射方式,包括查询、添加、修改和删除操作。针对每种关系,文章通过具体的例子说明如何配置映射文件,以及如何通过内连接优化查询性能,减少SQL语句的数量,提升效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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太麻烦~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值