目录
数据封装
Mybatis默认数据封装规则:
实体类属性名和数据库表的字段名一致,mybatis会自动封装
如果字段名和实体类属性名不一致解决办法:
1). 手动结果映射
在DeptMapper接口方法上,通过 @Results及@Result 进行手动结果映射。
@Results({@Result(column = "create_time", property = "createTime"), @Result(column = "update_time", property = "updateTime")}) @Select("select id, name, create_time, update_time from dept") public List<Dept> findAll();
2). 起别名
在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样。
@Select("select id, name, create_time createTime, update_time updateTime from dept") public List<Dept> findAll();
3). 开启驼峰命名(推荐)
如果字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射。驼峰命名规则: abc_xyz => abcXyz
表中字段名:abc_xyz
类中属性名:abcXyz
在application.yml中做如下配置,开启开关。
mybatis: configuration: map-underscore-to-camel-case: true
要使用驼峰命名前提是 实体类的属性 与 数据库表中的字段名严格遵守驼峰命名。
参数接收
简单参数接收
方案一:通过原始的
HttpServletRequest
对象获取请求参数/** * 根据ID删除部门 - 简单参数接收: 方式一 (HttpServletRequest) */ @DeleteMapping("/depts") public Result delete(HttpServletRequest request){ String idStr = request.getParameter("id"); int id = Integer.parseInt(idStr); System.out.println("根据ID删除部门: " + id); return Result.success(); }
方案二:通过Spring提供的
@RequestParam
注解,将请求参数绑定给方法形参@DeleteMapping("/depts") public Result delete(@RequestParam("id") Integer deptId){ System.out.println("根据ID删除部门: " + deptId); return Result.success(); }
@RequestParam
注解的value属性,需要与前端传递的参数名保持一致 。@RequestParam注解required属性默认为true,代表该参数必须传递,如果不传递将报错。 如果参数可选,可以将属性设置为false。
方案三:如果请求参数名与形参变量名相同,直接定义方法形参即可接收。(省略@RequestParam)
@DeleteMapping("/depts") public Result delete(Integer id){ System.out.println("根据ID删除部门: " + deptId); return Result.success(); }
json参数接收
- JSON格式的参数,通常会使用一个实体对象进行接收 。
- 规则:JSON数据的键名与方法形参对象的属性名相同,并需要使用
@RequestBody
注解标识。json格式的请求参数适用场景:主要在POST、PUT请求中, 在请求体传递请求参数
路径参数接收
/depts/1
,/depts/2
这种在url中传递的参数,我们称之为路径参数。 那么如何接收这样的路径参数呢 ?
- 路径参数:通过请求URL直接传递参数,使用{…}来标识该路径参数,需要使用
@PathVariable
获取路径参数。如下所示:如果路径参数名与controller方法形参名称一致,
@PathVariable
注解的value属性是可以省略的。
日志技术
Logback日志级别
日志级别指的是日志信息的类型,日志都会分级别,常见的日志级别如下(优先级由低到高):
日志级别 说明 记录方式 trace 追踪,记录程序运行轨迹 【使用很少】 log.trace("...") debug 调试,记录程序调试过程中的信息,实际应用中一般将其视为最低级别 【使用较多】 log.debug("...") info 记录一般信息,描述程序运行的关键事件,如:网络连接、io操作 【使用较多】 log.info("...") warn 警告信息,记录潜在有害的情况 【使用较多】 log.warn("...") error 错误信息 【使用较多】 log.error("...") 可以在配置文件
logback.xml
中,灵活的控制输出那些类型的日志。(大于等于配置的日志级别的日志才会输出)使用@Slf4j注解
@Slf4j @RequestMapping("/depts") @RestController public class DeptController { @Autowired private DeptService deptService; /** * 查询部门列表 */ //@RequestMapping(value = "/depts", method = RequestMethod.GET) @GetMapping public Result list(){ //System.out.println("查询部门列表"); log.info("查询部门列表"); List<Dept> deptList = deptService.findAll(); return Result.success(deptList); } }
PageHelper分页插件
代码实现
当使用了PageHelper分页插件进行分页,就无需再Mapper中进行手动分页了。 在Mapper中我们只需要进行正常的列表查询即可。在Service层中,调用Mapper的方法之前设置分页参数,在调用Mapper方法执行查询之后,解析分页结果,并将结果封装到PageResult对象中返回。
1). 在pom.xml引入依赖
<!--分页插件PageHelper--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.4.7</version> </dependency>
2). EmpMapper
/** * 查询所有的员工及其对应的部门名称 */ @Select("select e.*, d.name deptName from emp as e left join dept as d on e.dept_id = d.id") public List<Emp> list();
3). EmpServiceImpl
@Override public PageResult page(Integer page, Integer pageSize) { //1. 设置分页参数 PageHelper.startPage(page,pageSize); //2. 执行查询 List<Emp> empList = empMapper.list(); Page<Emp> p = (Page<Emp>) empList; //3. 封装结果 return new PageResult(p.getTotal(), p.getResult()); }
注意:
PageHelper实现分页查询时,SQL语句的结尾一定一定一定不要加分号(;).。
PageHelper只会对紧跟在其后的第一条SQL语句进行分页处理。
动态SQL标签
<if>
:判断条件是否成立,如果条件为true,则拼接SQL。<where>
:根据查询条件,来生成where关键字,并会自动去除条件前面多余的and或or。<!--定义Mapper映射文件的约束和基本结构--> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.itheima.mapper.EmpMapper"> <select id="list" resultType="com.itheima.pojo.Emp"> select e.*, d.name deptName from emp as e left join dept as d on e.dept_id = d.id <where> <if test="name != null and name != ''"> e.name like concat('%',#{name},'%') </if> <if test="gender != null"> and e.gender = #{gender} </if> <if test="begin != null and end != null"> and e.entry_date between #{begin} and #{end} </if> </where> </select> </mapper>
<foreach>
:是用来遍历循环,常见的属性说明:
- collection:集合名称
- item:集合遍历出来的元素/项
- separator:每一次遍历使用的分隔符
- open:遍历开始前拼接的片段
- close:遍历结束后拼接的片段
上述的属性,是可选的,并不是所有的都是必须的。 可以自己根据实际需求,来指定对应的属性。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.itheima.mapper.EmpExprMapper"> <!--批量插入员工工作经历信息--> <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> </mapper>
- <set>标签:会自动生成set关键字,会自动删除更新字段后多余的,
主键返回:@Options
在插入数据后,如何获取到主键值:
主键返回:
@Options(useGeneratedKeys = true, keyProperty = "id")
由于稍后,我们在保存工作经历信息的时候,需要记录是哪位员工的工作经历。 所以,保存完员工信息之后,是需要获取到员工的ID的,那这里就需要通过Mybatis中提供的主键返回功能来获取。
事务管理--Transactional注解
注解:@Transactional(默认出现运行时异常RuntimeException才会回滚)
作用:就是在当前这个方法执行开始之前来开启事务,方法执行完毕之后提交事务。如果在这个方法执行的过程当中出现了异常,就会进行事务的回滚操作。
位置:业务层的方法上、类上、接口上
方法上:当前方法交给spring进行事务管理
类上:当前类中所有的方法都交由spring进行事务管理
接口上:接口下所有的实现类当中所有的方法都交给spring 进行事务管理
@Transactional注解当中的两个常见的属性:
- 异常回滚的属性:
rollbackFor
在Spring的事务管理中,默认只有运行时异常 RuntimeException才会回滚。
如果还需要回滚指定类型的异常,可以通过rollbackFor属性来指定。
@Transactional(rollbackFor = Exception.class)
事务传播行为:
propagation
常见传播行为及应用场景:
REQUIRED:大部门场景
REQUIRES_NEW:希望两个方法在独立的事务中运行,互不影响
@Transactional(propagation = Propagation.REQUIRES_NEW)
全局异常处理器
我们该怎么样定义全局异常处理器?
定义全局异常处理器非常简单,就是定义一个类,在类上加上一个注解@RestControllerAdvice,加上这个注解就代表我们定义了一个全局异常处理器。
在全局异常处理器当中,需要定义一个方法来捕获异常,在这个方法上需要加上注解@ExceptionHandler。通过@ExceptionHandler注解当中的value属性来指定我们要捕获的是哪一类型的异常。
//全局异常处理器 @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler public Result handleException(Exception e) { log.error("服务器发生异常", e); return Result.error("服务器发生异常"); } }
@RestControllerAdvice = @ControllerAdvice + @ResponseBody
处理异常的方法返回值会转换为json后再响应给前端