缘博客
发布日期

员工管理:查询回显、ResultMap与动态更新

作者
  • 姓名
    社交账号

修改员工的两个阶段

员工编辑通常包含:

查询回显
+
提交修改

员工基本信息保存在 emp,工作经历保存在 emp_expr,所以详情不是简单单表查询。

实体对象中包含:

private List<EmpExpr> exprList;

用于封装多条工作经历。


根据ID查询员工详情

@GetMapping("/{id}")
public Result getInfo(@PathVariable Integer id) {
    log.info("根据id查询员工信息, id: {}", id);
    Emp emp = empService.getInfo(id);
    return Result.success(emp);
}

查询需要连接两张表:

select ...
from emp e
left join emp_expr ee on e.id = ee.emp_id
where e.id = ?;

一个员工可能对应多条工作经历,因此需要把多行结果封装为一个 Emp 和一个 List<EmpExpr>


resultTyperesultMap

课程结论:

  • 字段名和实体属性可以直接对应时,使用 resultType
  • 字段名无法直接对应,或者实体属性结构复杂时,使用 resultMap 手动封装。

自定义resultMap

<resultMap id="empResultMap" type="com.itheima.pojo.Emp">
    <id column="id" property="id" />
    <result column="username" property="username" />
    <result column="password" property="password" />
    <result column="name" property="name" />
    <result column="gender" property="gender" />
    <result column="image" property="image" />
    <result column="entry_date" property="entryDate" />
    <result column="dept_id" property="deptId" />
    <result column="create_time" property="createTime" />
    <result column="update_time" property="updateTime" />

    <collection property="exprList" ofType="com.itheima.pojo.EmpExpr">
        <id column="ee_id" property="id"/>
        <result column="ee_company" property="company"/>
        <result column="ee_job" property="job"/>
        <result column="ee_begin" property="begin"/>
        <result column="ee_end" property="end"/>
        <result column="ee_empid" property="empId"/>
    </collection>
</resultMap>

collection 用于映射集合属性,property="exprList" 对应 Emp 中的列表,ofType 指定集合元素类型。


查询SQL字段别名

为避免 empemp_expr 中同名字段冲突,课程给工作经历字段起别名:

<select id="getById" resultMap="empResultMap">
    select
        e.*,
        ee.id ee_id,
        ee.company ee_company,
        ee.job ee_job,
        ee.begin ee_begin,
        ee.end ee_end,
        ee.emp_id ee_empid
    from emp e
    left join emp_expr ee on e.id = ee.emp_id
    where e.id = #{id}
</select>

修改员工数据

@PutMapping
public Result update(@RequestBody Emp emp) {
    log.info("修改员工信息, {}", emp);
    empService.update(emp);
    return Result.success();
}

Service 中的处理流程:

更新员工基本信息
删除原工作经历
插入新的工作经历

课程代码:

@Transactional(rollbackFor = Exception.class)
public void update(Emp emp) {
    emp.setUpdateTime(LocalDateTime.now());
    empMapper.updateById(emp);

    empExprMapper.deleteByEmpIds(Arrays.asList(emp.getId()));

    Integer empId = emp.getId();
    List<EmpExpr> exprList = emp.getExprList();

    if (!CollectionUtils.isEmpty(exprList)) {
        exprList.forEach(empExpr -> empExpr.setEmpId(empId));
        empExprMapper.insertBatch(exprList);
    }
}

因为涉及多次数据库操作,所以同样需要事务。


动态更新

固定 Update 会更新所有字段,不够灵活。MyBatis 可以通过 <if> 根据实际参数决定是否生成字段:

<if test="name != null and name != ''">
    name = #{name},
</if>

多个 <if> 容易产生末尾多余逗号,因此使用 <set>

<update id="updateById">
    update emp
    <set>
        <if test="username != null and username != ''">
            username = #{username},
        </if>
        <if test="name != null and name != ''">
            name = #{name},
        </if>
        <if test="gender != null">
            gender = #{gender},
        </if>
        <if test="updateTime != null">
            update_time = #{updateTime},
        </if>
    </set>
    where id = #{id}
</update>

这样就能实现“传哪些字段,就更新哪些字段”。


核心知识点

左连接查询
+
resultMap
+
collection
+
动态SQL
+
<if>
+
<set>
+
事务

这一部分比普通单表 CRUD 更接近真实业务中的复杂数据处理。