如何实现简单的员工删除功能
内容概览:
- 删除员工功能 - 支持批量删除
- 修改员工功能 - 查询回显 + 数据更新
- 异常处理机制 - 全局异常处理器
- 员工信息统计 - 职位统计 + 性别统计
1. 批量删除员工功能
1.1 需求分析
- 支持单个 / 批量删除员工(通过 ID 列表操作)
- 需同时删除员工基本信息(
emp
表)和相关工作经历(emp_expr
表)
- 业务规则:确保主从表数据一致性,通过事务保证原子性
1.2 核心代码实现
Controller 层
1
2
3
4
5
6
7
8
9
10
|
@RestController
@RequestMapping("/emps")
public class EmpController {
@DeleteMapping
public Result delete(Integer[] ids){
log.info("员工删除: {}",Arrays.toString(ids));
//调用service层代码略
return Result.success();
}
}
|
1
2
3
4
5
6
7
8
9
10
|
@RestController
@RequestMapping("/emps")
public class EmpController {
@DeleteMapping
public Result delete(@RequestParam("ids") List<Integer> ids) {
log.info("执行批量删除:ids={}", ids);
empService.deleteByIds(ids);
return Result.success();
}
}
|
Service 层(事务控制)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Autowired
private EmpExprMapper empExprMapper;
@Override
@Transactional // 声明式事务管理
public void deleteByIds(List<Integer> ids) {
// 1. 删除员工基本信息
empMapper.deleteByIds(ids);
// 2. 删除关联的工作经历
empExprMapper.deleteByEmpIds(ids);
}
}
|
Mapper 层(MyBatis 动态 SQL)
xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<!-- empMapper.xml -->
<delete id="deleteByIds">
DELETE FROM emp
WHERE id IN
<!-- 遍历ids集合,生成IN条件 -->
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id} <!-- 插入当前id值 -->
</foreach>
</delete>
<!-- empExprMapper.xml -->
<delete id="deleteByEmpIds">
DELETE FROM emp_expr
WHERE emp_id IN
<foreach collection="empIds" item="empId" open="(" close=")" separator=","> <!-- 遍历empIds集合,生成IN条件 -->
#{empId} <!-- 插入当前empId值 -->
</foreach>
</delete>
|
2. 修改员工功能
2.1 查询回显实现(复杂结果集映射)
数据库表关联查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<resultMap id="empWithExprResultMap" type="Emp">
<!-- 主表字段映射 -->
<id column="emp_id" property="id" />
<result column="username" property="username" />
<result column="name" property="name" />
<!-- 一对多关联:工作经历列表 -->
<collection property="exprList" ofType="EmpExpr">
<id column="expr_id" property="id" />
<result column="company" property="company" />
<result column="start_time" property="startTime" />
<result column="end_time" property="endTime" />
</collection>
</resultMap>
<select id="getEmpById" resultMap="empWithExprResultMap">
SELECT
e.id AS emp_id,
e.username,
e.name,
ee.id AS expr_id,
ee.company,
ee.start_time,
ee.end_time
FROM emp e
LEFT JOIN emp_expr ee ON e.id = ee.emp_id
WHERE e.id = #{id}
</select>
|
2.2 更新员工实现(动态 SQL + 事务)

主表动态更新
xml
1
2
3
4
5
6
7
8
9
10
|
<update id="updateEmp">
UPDATE emp
<set>
<if test="username != null">username = #{username},</if>
<if test="name != null">name = #{name},</if>
<if test="gender != null">gender = #{gender},</if>
update_time = NOW()
</set>
WHERE id = #{id}
</update>
|
Service 层事务逻辑
java
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Override
@Transactional
public void updateEmp(Emp emp) {
// 1. 更新基本信息
empMapper.updateEmp(emp);
// 2. 先删除旧工作经历
empExprMapper.deleteByEmpId(emp.getId());
// 3. 新增新工作经历(如果有)
if (!CollectionUtils.isEmpty(emp.getExprList())) {
emp.getExprList().forEach(expr -> expr.setEmpId(emp.getId()));
empExprMapper.insertBatch(emp.getExprList());
}
}
|
3. 全局异常处理机制
3.1 统一异常处理器
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理所有未捕获异常
@ExceptionHandler(Exception.class)
public Result<String> handleGlobalException(Exception ex) {
log.error("全局异常:{}", ex.getMessage(), ex);
return Result.error("服务器内部错误,请联系管理员");
}
// 处理数据库唯一约束异常(如手机号重复)
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public Result<String> handleDuplicateException(SQLIntegrityConstraintViolationException ex) {
if (ex.getMessage().contains("Duplicate entry")) {
return Result.error("数据已存在,请勿重复提交");
}
return Result.error("数据库操作失败");
}
// 处理业务校验异常
@ExceptionHandler(BusinessException.class)
public Result<String> handleBusinessException(BusinessException ex) {
return Result.error(ex.getMessage());
}
}
|
4. 员工信息统计功能
4.1 职位统计(SQL 分组 + 数据转换)
Mapper 层统计 SQL
xml
1
2
3
4
5
6
7
8
9
10
11
12
|
<select id="countJobStatistics" resultType="map">
SELECT
CASE job
WHEN 1 THEN '班主任'
WHEN 2 THEN '讲师'
ELSE '其他职位'
END AS position,
COUNT(*) AS count
FROM emp
GROUP BY job
ORDER BY count DESC
</select>
|
Service 层数据封装
java
1
2
3
4
5
6
7
8
9
10
|
public Map<String, Object> getJobStatistics() {
List<Map<String, Object>> list = empMapper.countJobStatistics();
List<String> positions = list.stream().map(m -> (String) m.get("position")).collect(Collectors.toList());
List<Integer> counts = list.stream().map(m -> (Integer) m.get("count")).collect(Collectors.toList());
return new HashMap<>() {{
put("labels", positions);
put("data", counts);
}};
}
|
4.2 性别统计(使用 IF 函数分组)
Mapper 层统计 SQL
xml
1
2
3
4
5
6
7
|
<select id="countGenderStatistics" resultType="map">
SELECT
IF(gender = 1, '男', '女') AS gender,
COUNT(*) AS count
FROM emp
GROUP BY gender
</select>
|
返回结果示例
json
1
2
3
4
|
{
"gender": ["男", "女"],
"count": [15, 8]
}
|
🎯 关键知识点总结
1. 批量操作处理
- MyBatis 技巧:使用
<foreach>
标签实现 IN 条件,collection
属性支持List
/Array
- 参数传递:Controller 层需用
@RequestParam("ids")
接收数组参数
2. 复杂结果映射
- 一对多关联:通过
<collection>
标签映射主从表关系,需使用别名避免字段冲突
- 性能优化:使用
LEFT JOIN
保留主表数据,即使从表无记录也能正常回显
3. 事务管理要点
- 注解范围:
@Transactional
应添加在 Service 层方法上,而非 Mapper 层
- 操作顺序:更新关联数据时建议先删除旧数据再插入新数据,避免唯一键冲突
4. 异常处理最佳实践
- 分层处理:区分业务异常(
BusinessException
)和技术异常(数据库异常)
- 友好提示:对唯一性约束异常等特定场景返回明确错误信息,避免暴露数据库细节
5. 统计查询技巧
- 数据转换:使用
CASE WHEN
或IF
函数将数据库枚举值转换为前端展示文本
- 结果适配:将统计结果封装为
{labels, data}
格式,直接对接 ECharts 等图表组件
🚦 联调测试要点
1. 批量删除测试
- 单条测试:传入单个 ID,验证
emp
和emp_expr
表对应记录是否删除
- 批量测试:传入多个 ID(如 [1,3,5]),检查事务是否保证全部成功或回滚
- 边界测试:传入空列表、重复 ID,验证接口是否抛出合理异常
2. 修改功能测试
- 基本信息更新:修改姓名、手机号等字段,验证数据库是否正确更新
- 工作经历变更:新增 / 删除工作经历条目,确保旧数据清除且新数据正确插入
- 唯一约束测试:尝试修改手机号为已存在的值,验证是否触发唯一性异常
3. 统计功能验证
- 数据分组:检查不同职位 / 性别的统计结果是否与实际数据一致
- 特殊值处理:测试
gender
为NULL
的记录是否被正确归类(可自定义默认值)
- 格式校验:确认返回数据结构符合前端图表组件的要求(如数组顺序、字段名)
📚 扩展建议
- 权限控制:为删除 / 修改功能添加角色校验(如仅管理员可操作)
- 日志审计:记录员工操作日志(操作人、时间、数据前后对比)
- 性能优化:对高频查询添加缓存(如使用 Redis 存储统计结果)
- 分页支持:在统计接口中添加分页参数,避免大数据量下性能问题
通过本指南,可完整实现企业级员工管理系统的核心功能,覆盖 CRUD、事务控制、异常处理及数据统计等关键场景,满足中大型应用的业务需求。