resultType
Mybatis中封装查询结果,什么时候用 resultType,什么时候用resultMap ?
- 如果查询返回的字段名与实体的属性名可以直接对应上,用resultType 。
- 如果查询返回的字段名与实体的属性名对应不上,或实体属性比较复杂,可以通过resultMap手动封装 。
package site.suiyue.pojo;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class Emp {
private Integer id; //ID,主键
private String username; //用户名
private String password; //密码
private String name; //姓名
private Integer gender; //性别, 1:男, 2:女
private String phone; //手机号
private Integer job; //职位, 1:班主任,2:讲师,3:学工主管,4:教研主管,5:咨询师
private Integer salary; //薪资
private String image; //头像
private LocalDate entryDate; //入职日期
private Integer deptId; //关联的部门ID
private LocalDateTime createTime; //创建时间
private LocalDateTime updateTime; //修改时间
//封装部门名称数
private String deptName; //部门名称
//封装员工工作经历信息
private List exprList;
}
<resultMap id="empResultMap" type="site.suiyue.pojo.Emp">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="name" property="name"/>
<result column="password" property="password"/>
<result column="phone" property="phone"/>
<result column="entry_date" property="entryDate"/>
<result column="gender" property="gender"/>
<result column="image" property="image"/>
<result column="job" property="job"/>
<result column="salary" property="salary"/>
<result column="dept_id" property="deptId"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
<collection property="exprList" ofType="site.suiyue.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>
<select id="findById" resultMap="empResultMap">
select e.*,
ee.id ee_id,
ee.emp_id ee_empid,
ee.begin ee_begin,
ee.end ee_end,
ee.company ee_company,
ee.job ee_job
from emp e left join emp_expr ee on e.id = ee.emp_id
where e.id = #{id}
</select>
异常处理
1.建立exception包
2.编写“自定义业务异常”
继承 RuntimeException,这样在业务代码中抛出时不需要显式地在方法签名上写 throws
package site.suiyue.exception;
public class BusinessException extends RuntimeException {
private Integer code;
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
}
public Integer getCode() {
return code;
}
}
3.编写“全局异常处理器”
使用 @RestControllerAdvice 拦截所有 Controller 抛出的异常。@RestControllerAdvice = @ControllerAdvice + @ResponseBody
通过@ExceptionHandler注解当中的value属性来指定我们要捕获的是哪一类型的异常。
处理异常的方法返回值会转换为json后再响应给前端
package site.suiyue.exception;
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 捕获自定义的业务异常
* 比如:密码错误、库存不足等
*/
@ExceptionHandler(BusinessException.class)
public Result handleBusinessException(BusinessException e) {
log.warn("业务逻辑异常: {}", e.getMessage());
return Result.error(e.getCode(), e.getMessage());
}
/**
* 捕获 Spring 校验参数失败的异常 (如 @NotBlank 校验不通过)
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleValidationException(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getFieldError().getDefaultMessage();
log.warn("参数校验失败: {}", message);
return Result.error(400, message);
}
/**
* 兜底处理:捕获所有不可预知的运行时异常
* 比如:空指针、数据库连接超时、数组越界
*/
@ExceptionHandler(Exception.class)
public Result handleException(Exception e) {
// 记录详细堆栈日志,方便排查问题
log.error("系统运行异常: ", e);
// 给前端一个友好的提示,不暴露具体代码错误
return Result.error(500, "服务器开小差了,请稍后再试");
}
}
4.在业务代码中使用
@GetMapping("/{id}")
public Result findById(@PathVariable Integer id) {
Emp emp = empService.getById(id);
if (emp == null) {
// 直接抛出,ExceptionHandler 会自动抓取并返回给前端
//{"code":404, "msg":"员工不存在", "data":null}
throw new BusinessException(404, "员工不存在");
}
return Result.success(emp);
}
@Mapkey
如果查询的记录往Map中封装,可以通过@MapKey注解指定返回的map中的唯一标识是那个字段。【也可以不指定】
@MapKey("pos")
List<Map<String,Object>> countEmpJobData();
<!-- 统计各个职位的员工人数 -->
<select id="countEmpJobData" resultType="java.util.Map">
select
(case job when 1 then '班主任'
when 2 then '讲师'
when 3 then '学工主管'
when 4 then '教研主管'
when 5 then '咨询师'
else '其他' end) pos,
count(*) total
from emp group by job
order by total
</select>
<select id="reportStudentDegreeData" resultType="java.util.Map">
select count(*) as value,
case when degree=1 then '初中'
when degree=2 then '高中'
when degree=3 then '大学'
when degree=4 then '硕士'
when degree=5 then '博士'
else '其他'
end as name
from student group by degree;
</select>
case when:
- 语法一:case when cond1 then res1 [ when cond2 then res2 ] else res end ;
- 含义:如果 cond1 成立, 取 res1。 如果 cond2 成立,取 res2。 如果前面的条件都不成立,则取 res。
- 语法二(仅适用于等值匹配):case expr when val1 then res1 [ when val2 then res2 ] else res end ;
- 含义:如果 expr 的值为 val1 , 取 res1。 如果 expr 的值为 val2 ,取 res2。 如果前面的条件都不成立,则取 res。
if/ifnull
if函数语法:if(条件, 条件为true取值, 条件为false取值)
ifnull函数语法:ifnull(expr, val1) 如果expr不为null,取自身,否则取val1
<!-- 统计员工的性别信息 -->
<select id="countEmpGenderData" resultType="java.util.Map">
select
if(gender = 1, '男', '女') as name,
count(*) as value
from emp group by gender ;
</select>
Comments NOTHING