删除员工:
- 删除员工信息,根据员工的id删除
- 其实批量删除就是一种特殊的批量删除,所以,删除员工的功能,我们只需要开发一个接口就可以了。
删除员工的逻辑分析:
controller层获取请求的参数:
接收请求参数:DELETE /emps?ids=1,2,3
通过数组来接收:
自己写的controller
/**
* 批量删除 参数--数组
* @param ids
* @return
*/
@DeleteMapping
public Result delByIds(Integer[] ids){
log.info("要删除的数据:{}", Arrays.toString(ids));
return Result.success();
}
在Apifox里面测试:
在idea的控制台查看接收到的参数:
通过集合删除:
/**
* 批量删除
* @param ids
* @return
*/
@DeleteMapping
public Result del(@RequestParam List<Integer> ids){
log.info("集合接收批量删除的id{}",ids);
empService.delete(ids);
return Result.success();
}
在Apifox测试:
在控制台查看要删除的数据id
编写empService接口:
编写empServiceImpl的实现类:
因为删除员工基本信息的时候,还有把员工的工作经历删除,所以要删除两张表,同时为了保证数据库的完整性和一致性,我开启了事务。
@Transactional
@Override
public void delete(List<Integer> ids) {
//调用批量删除员工的接口
empMapper.delByIds(ids);
//调用批量删除工作经历的接口
empExprMapper.delByEmpId(ids);
}
编写EmpMapper接口:
void delByIds(List<Integer> ids);
编写EmpMapperXml配置文件
<delete id="delByIds">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
编写EmpExprMapper接口:
void delByEmpId(List<Integer> ids);
现在就可以在Apifox里面测试了:
最后总结:
修改员工:
大概执行思路:
查询回显:
自定义结果集:
resultMap标签:
Mybatis中封装查询结果,什么时候用 resultType,什么时候用resultMap?
- 如果查询返回的字段名与实体的属性名可以直接对应上,用resultType。
- 如果查询返回的字段名与实体的属性名对应不上,或实体属性比较复杂,可以通过resultMap手动封装
resultMap标签详解:
用于将查询结果映射到Java对象的标签。
id:此resultMap标签的唯一标识
type:数据要映射的类型
<id></id>标签
<id></id>常用于封装数据库表的主键id
常用的属性:
column:要映射的数据库字段
property:要映射的数据库属性名
<result></result>标签
<result></result>常用于封装数据库表的普通字段
常用的属性:
column:要映射的数据库字段
property:要映射的数据库属性名
<collection></collection>标签:
<collection></collection>常用于封装一个集合的数据
property:要封装的数据类型ofType:要封装的单条数据类型
在collection标签里面也是写
id标签和result标签
编写EmpController层接口:
/**
* 根据id查询员工信息
* @param id
* @return
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id){
Emp emp = empService.getById(id);
return Result.success(emp);
}
编写:EmpService接口:
Emp getById(Integer id);
编写EmpServiceImpl实现类:
@Override
public Emp getById(Integer id) {
return empMapper.getById(id);
}
编写EmpMapper接口:
Emp getById(Integer id);
编写EmpMapperXml配置文件:
<resultMap id="emp_expr_map" type="com.sde.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="phone" property="phone"/>
<result column="job" property="job"/>
<result column="salary" property="salary"/>
<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.sde.pojo.EmpExpr">
<id column="er_id" property="id"/>
<result column="er_emp_id" property="empId" />
<result column="er_begin" property="begin" />
<result column="er_end" property="end" />
<result column="er_company" property="company" />
<result column="er_job" property="job" />
</collection>
</resultMap>
<select id="getById" resultMap="emp_expr_map">
select e.*,er.id er_id,er.emp_id er_emp_id,er.begin er_begin,
er.end er_end,er.company er_company,er.job er_job from emp e left join emp_expr er
on e.id = er.emp_id where e.id = #{id}
</select>
前后端联调测试:
修改信息:
根据id修改员工信息,但是我们思考一下,在修改员工信息的时候,我们还要对员工的工作经历进行处理。想到了一个简单便捷的方法,就是不管我的员工经历信息,改没改,我都要以最后提交的为主。先删后加。
编写EmpController层:
@PutMapping
public Result update(@RequestBody Emp emp){
log.info("要修改的参数信息:"+emp);
empService.update(emp);
return Result.success();
}
编写EmpService接口:
void update(Emp emp);
编写EmpServiceImpl实现类:
@Transactional
@Override
public void update(Emp emp) {
emp.setUpdateTime(LocalDateTime.now());
//先删除员工经历表的数据
empExprMapper.delByEmpId(Arrays.asList(emp.getId()));
//修改员工基本信息
empMapper.update(emp);
//添加员工的工作经历信息
List<EmpExpr> exprList = emp.getExprList();
if (!CollectionUtils.isEmpty(exprList)){
exprList.forEach(empExpr -> {
empExpr.setEmpId(emp.getId());
});
empExprMapper.insertBatch(exprList);
}
}
编写 EmpMapper接口:
void update(Emp emp);
编写EmpMapperXml配置文件:
<update id="update">
update emp
<set>
<if test="username != null">
username = #{username},
</if>
<if test="name != null">
name = #{name},
</if>
<if test="gender != null">
gender = #{gender},
</if>
<if test="phone != null">
phone = #{phone},
</if>
<if test="image != null">
image = #{image},
</if>
<if test="deptId != null">
dept_id = #{deptId},
</if>
<if test="entryDate != null">
entry_date = #{entryDate},
</if>
<if test="job != null">
job = #{job},
</if>
<if test="salary != null">
salary = #{salary},
</if>
</set>
<where>
id = #{id}
</where>
</update>
编写EmpExprMapper接口:
批量删除员工的工作经历:
void delByEmpId(List<Integer> ids);
编写批量添加的接口:
/**
* 批量添加员工经历的数据
* @param exprList
*/
void insertBatch(List<EmpExpr> exprList);
编写EmpExprMapperxml配置文件:
<insert id="insertBatch">
insert into emp_expr(emp_id,begin,end,company,job) values
<foreach collection="exprList" item="expr" separator=",">
(#{expr.empId},#{expr.begin},#{expr.end},#{expr.company},#{expr.job})
</foreach>
</insert>
<delete id="delByEmpId">
delete from emp_expr where emp_id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
异常处理:
在项目开发中难免会出现异常,这是不可避免的。在前面我们编写的接口中,也会出现报错,但是我们都是怎么直接就把错误的信息返回给前端页面了。
现在各层代码出现异常,我们是如何进行处理的?答案是:未做处理。
可以在学到javase的时候出现异常可以 抛出异常和try/catch,但是这样显得太繁琐
我们可以定义一个全局异常处理器
我们在com.sde包下创建一个exception包,里面创建一个全局异常处理器类
在类上面添加@RestControllerAdvice注解
在方法上面添加@ExceptionHandle注解:
GlobalExceptionHandle全局异常类
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandle {
@ExceptionHandler
public Result ExceptionHandle(Exception e){
log.error("程序运行出错了...",e);
return Result.error("对不起,程序运行出错,请联系管理员~");
}
@ExceptionHandler
public Result handleBusinessException(BusinessException e){
log.info("程序运行出错");
return Result.error(e.getMessage());
}
}
这样我们人为程序制造一个异常。
if (true){
throw new RuntimeException("人为制造的异常");
}
前后端联调测试:
看看idea控制台
我们定义的全局异常,生效了。
假如我们有很多异常,不同种类的异常时如何捕获的呢??
下面我人为写一个io异常,看看是先执行Exception还是执行IoException异常
@ExceptionHandler
public Result ioException(IOException e){
log.info("精准匹配异常");
return Result.error("出现io异常");
}
前后联调测试:
看看idea控制台:
可以发现,我人为制造的io异常捕获到了这个异常数据,
全局异常捕获,先是小范围的精准匹配,然后要是匹配不到,就像大范围寻找,最后没有,就会抛出父类的异常,Exception异常。
员工信息统计:
职位统计:
执行思路流程:
mysql的case函数:
语法一:
case when cond1 then res1 [when cond2 then res2] else res end ;
语法二:
语法二(适用于等值匹配):
编写JobData实体类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JobData {
private List jobList;
private List dataList;
}
编写 ReportController层:
/**
* 员工和职位人数统计
* @return
*/
@GetMapping("/empJobData")
public Result empJobData(){
JobData jobData = reportService.getJobData();
return Result.success(jobData);
}
编写reportService接口:
JobData getJobData();
编写ReportServiceImpl实现类:
@Override
public JobData getJobData() {
List<Map> jobData = empMapper.getJobData();
System.out.println(jobData);
List<Object> jobList = jobData.stream().map(map -> {
return map.get("pos");
}).toList();
System.out.println(jobList);
List<Object> countList = jobData.stream().map(map -> {
return map.get("posCount");
}).toList();
return new JobData(jobList,countList);
}
编写EmpMapper接口:
@MapKey("pos")
List<Map> getJobData();
编写EmpMapperxml配置文件:
<select id="getJobData" resultType="java.util.Map">
select count(*) posCount,
(case job when 1 then '班主任'
when 2 then '讲师'
when 3 then '学工主管'
when 4 then '教研主管'
when 5 then '咨询师'
else '其他' end) pos
from emp group by job;
</select>
前后端联调测试:
性别统计:
if流程控制函数:
- if(expr,val1,val2):如果表达式expr成立,取val1,否则取val2
- ifnull(expr,val1):如果expr不为null,取自身,否则取val1
如果查询的记录往Map中封装,可以通过@MapKey注解指定返回的map中的唯一标识是那个字段。【也可以不指定】
编写ReportController层接口:
/**
* 员工性别统计
* @return
*/
@GetMapping("/empGenderData")
public Result empGenderData(){
List<Map> mapList = reportService.getGenderData();
return Result.success(mapList);
}
编写ReportService接口:
List<Map> getGenderData();
编写ReportServiceImpl实现类:
@Override
public List<Map> getGenderData() {
return empMapper.genderData();
}
编写EmpMapper接口:
List<Map> genderData();
编写EmpMapperxml实现类:
<select id="genderData" resultType="java.util.Map">
select
if(gender = 1 ,'男性员工','女性员工') name
,count(*) value from emp group by gender;
</select>
前后端联调测试: