一、前言
实际开发中修改业务,必须先查询回显原有数据,再做更新操作;本篇结合三层架构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、MyBatis resultType 和 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>
三、修改业务开发
业务逻辑
//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
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);
}
性别统计逻辑和职位统计完全一致,返回数据给前端渲染饼图。
六、知识点总结📝
- resultType:字段属性匹配直接封装;resultMap用于字段不匹配 / 多表联查。
- <set>动态标签用于 update,自动去除末尾逗号。




