一、前言
实际开发中修改业务,必须先查询回显原有数据,再做更新操作;本篇结合三层架构Controller‑Service‑Mapper,讲解 MyBatis 结果映射、动态 SQL、全局异常处理器、统计图表业务完整开发流程。
二、修改前:数据查询回显
1、三层调用流程
浏览器请求 → Controller 接收参数 → Service 调用业务逻辑 → Mapper 执行多表查询,查询数据返回前端页面做回显。
2、SpringMVC 三种参数接收注解
| 注解 | 作用 | 使用场景 |
|---|---|---|
@RequestParam | 接收 url 问号后参数 | xxx?id=1 |
@RequestBody | 接收 post 的 json 对象 | 前端传递 json 大对象 |
@PathVariable | 接收路径变量 | xxx/{id}路径占位符 |
@GetMapping("/{id}") public Result getInfo(@PathVariable Integer id){ //业务查询逻辑 }3、MyBatisresultType和resultMap
resultType:数据库字段名 和 实体类属性名完全对应,直接自动封装。resultMap:字段与属性不匹配、多表联查、嵌套复杂实体,手动配置映射关系。
💡多表联查场景,使用 resultMap 手动配置,解决字段封装问题。
<select id="getById" resultType="xxx.pojo.Emp"> select e.*,ee.* from emp e left join emp_expr ee on e.id=ee.emp_id where e.id=#{id} </select>三、修改业务开发
业务逻辑
- 根据 id 查询原有数据回显页面
- 提交修改表单,更新员工基础信息
- 删除旧的员工经历数据,批量插入新经历数据
//service层伪代码 @Override public void update(Emp emp) { //1 更新员工基础信息 empMapper.update(emp); //2 删除旧的工作经历 empExprMapper.deleteByEmpId(emp.getId()); //3 判断集合非空,批量新增工作经历 if(CollectionUtils.isNotEmpty(emp.getEmpExprList())){ empExprMapper.insertBatch(emp.getEmpExprList()); } }MyBatis 动态 SQL <set>标签
<set>标签用于 update 语句,自动去掉多余逗号,实现按需字段更新。
<update id="update"> update emp <set> <if test="username != null">username=#{username},</if> <if test="gender != null">gender=#{gender},</if> <if test="updateTime != null">update_time=#{updateTime}</if> </set> where id = #{id} </update>⚠️开发要点:使用CollectionUtils.isNotEmpty()判断集合非空,防止空集合执行 SQL 报错。
四、全局异常处理器
问题
原始开发中,每层代码写大量try‑catch,代码臃肿,重复度高。
解决方案:@RestControllerAdvice全局异常处理器
统一捕获整个项目抛出的异常,统一返回 Result 结果,不用每个 controller 写 try‑catch。
核心注解:
@RestControllerAdvice:作用所有 controller@ExceptionHandler:指定捕获哪一类异常
@RestControllerAdvice public class GlobalExceptionHandler { //捕获通用异常 @ExceptionHandler(Exception.class) public Result handleException(Exception e){ e.printStackTrace(); return Result.error("出错,请联系管理员"); } //捕获数据库主键重复异常,细分异常提示 @ExceptionHandler(DuplicateKeyException.class) public Result handleDuplicateKeyException(DuplicateKeyException e){ return Result.error("数据已存在"); } }💡可以写多个@ExceptionHandler,细分不同异常类型,给前端精准提示
1、case when 条件统计 SQL
用于数据库层面做分类统计,例如统计各个职位人数。
select case job when '1' then '班主任' when '2' then '讲师' else '其他' end pos, count(*) num from emp group by job;2、返回 List<Map<String,Object>>
统计结果没有对应实体类,直接返回List<Map<String,Object>>,mybatis 直接把每行记录封装为 map,key 为列名,value 为值。
Mapper 接口:
List<Map<String,Object>> getJobCount();3、Service 数据组装
查询得到 List<Map>,再转换为前端 ECharts 需要的labels[]、values[]格式。
@Override public ReportVo getJobData() { List<Map<String, Object>> list = empMapper.getJobCount(); List<String> jobList = new ArrayList<>(); List<Integer> numList = new ArrayList<>(); for (Map<String, Object> map : list) { jobList.add(map.get("pos").toString()); numList.add((Integer) map.get("num")); } return new ReportVo(jobList,numList); }性别统计逻辑和职位统计完全一致,返回数据给前端渲染饼图。
六、知识点总结📝
- 修改业务流程:先查询回显 → 提交修改 → 更新主表、处理子表数据。
- 参数接收:
@PathVariable路径变量,@RequestBody接收 json,@RequestParam接收 url 参数。 - MyBatis:
resultType:字段属性匹配直接封装;resultMap用于字段不匹配 / 多表联查。<set>动态标签用于 update,自动去除末尾逗号。
- 集合判空优先使用
CollectionUtils.isNotEmpty(),避免空集合操作报错。 - 全局异常:
@RestControllerAdvice + @ExceptionHandler统一捕获异常,区分不同异常返回不同提示。 - 统计业务:SQL
case when做分类统计,返回List<Map<String,Object>>处理无实体的查询结果,组装 ECharts 图表数据