SpringBootWeb案例 Part 2
目录
3. 员工管理
3.1 分页查询
3.1.1 基础分页
3.1.1.1 需求分析
3.1.1.2 接口文档
3.1.1.3 思路分析
3.1.1.4 功能开发
PageBean
3.1.1.5 功能测试
3.1.1.6 前后端联调
3.1.2 分页插件{分页查询-PageHelper插件}
3.1.2.1 介绍
官网:
3.1.2.2 代码实现
EmpController
EmpService
3.1.2.3 测试
补充:分页插件的两个重要参数:
helperDialect:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置helperDialect属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:oracle,mysql,mariadb,sqlite,hsqldb,postgresql,db2,sqlserver,informix,h2,sqlserver2012,derby特别注意:使用 SqlServer2012 数据库时,需要手动指定为 sqlserver2012,否则会使用 SqlServer2005 的方式进行分页。你也可以实现 AbstractHelperDialect,然后配置该属性为实现类的全限定名称即可使用自定义的实现方法。
reasonable:分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。
3.2 分页查询(带条件)
3.2.2 条件分页查询 - 思路分析
3.2.3 功能开发
3.2.4 功能测试
3.2.5 前后端联调
3.3 删除员工
3.3.1 需求
3.3.2 接口文档
3.3.3 思路分析
@PathVariable
@DeleteMapping
Mybatis中的动态SQL:foreach
3.3.4 功能开发
响应数据:json格式
EmpController
3.3.5 功能测试
3.3.6 前后端联调
3. 员工管理
完成了部门管理的功能开发之后,我们进入到下一环节员工管理功能的开发。
基于以上原型,我们可以把员工管理功能分为:
-
分页查询
-
带条件的分页查询
-
删除员工
-
新增员工
-
修改员工
那下面我们就先从分页查询功能开始学习。
3.1 分页查询
3.1.1 基础分页
3.1.1.1 需求分析
我们之前做的查询功能,是将数据库中所有的数据查询出来并展示到页面上,试想如果数据库中的数据有很多(假设有十几万条)的时候,将数据全部展示出来肯定不现实,那如何解决这个问题呢?
使用分页解决这个问题。每次只展示一页的数据,比如:一页展示10条数据,如果还想看其他的数据,可以通过点击页码进行查询。
要想从数据库中进行分页查询,我们要使用LIMIT
关键字,格式为:limit 开始索引 每页显示的条数
-- 分页查询语法
-- 参数1:起始索引 = (页码 - 1) * 每页展示记录数
-- 参数2:每页展示记录数 = 查询返回记录数
select * from emp limit 0,10;-- 查询第一页数据,每页展示5条记录
select * from emp limit 0,5;-- 查询第二页数据,每页展示5条记录
select * from emp limit 5,5;-- 查询第三页数据,每页展示5条记录
select * from emp limit 10,5;
观察以上SQL语句,发现: 开始索引一直在改变 , 每页显示条数是固定的
开始索引的计算公式: 开 / 起始索引 = (当前页码 - 1) * 每页显示条数
我们继续基于页面原型,继续分析,得出以下结论:
-
前端在请求服务端时,传递的参数
-
当前页码 page
-
每页显示条数 pageSize
-
-
后端需要响应什么数据给前端
-
所查询到的数据列表(因为数据列表有多条记录,因此存储到List 集合当中)
-
总记录数
-
后台给前端返回的数据包含:List集合(数据列表)、total(总记录数)
而这两部分我们通常封装到PageBean对象中,并将该对象转换为json格式的数据响应回给浏览器。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {
private Long total; //总记录数
private List rows; //当前页数据列表
}
3.1.1.2 接口文档
员工列表查询
-
基本信息
- 请求参数
参数格式:queryString
参数说明:
参数名 称 | 是否必 须 | 示例 | 备注 |
name | 否 | 张 | 姓名 |
gender | 否 | 1 | 性别 , 1 男 , 2 女 |
begin | 否 | 2010-01- 01 | 范围匹配的开始时间(入职日期) |
end | 否 | 2020-01- 01 | 范围匹配的结束时间(入职日期) |
page | 是 | 1 | 分页查询的页码,如果未指定,默认为1 |
pageSize | 是 | 10 | 分页查询的每页记录数,如果未指定,默认为10 |
请求数据样例:
2.1.3 响应数据
参数格式:application/json
参数说明:
响应数据样例:
3.1.1.3 思路分析
分页查询需要的数据,封装在PageBean对象中:
3.1.1.4 功能开发
通过查看接口文档:员工列表查询
请求路径:/emps
请求方式:GET
请求参数:跟随在请求路径后的参数字符串。 例:/emps?page=1&pageSize=10
响应数据:json格式
EmpController
package com.gch.controller;import com.gch.pojo.PageBean;
import com.gch.pojo.Result;
import com.gch.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/**员工管理控制器*/
@Slf4j
@RestController
@RequestMapping("")
public class EmpController {@Autowiredprivate EmpService empService;/*** 条件分页查询* @param page => 分页查询的页码* @param pageSize => 分页查询的每页展示记录数* 默认值的设置可以通过注解@RequestParam中的defaultValue()属性来指定默认值* 注意:形参page与pageSize需要于接口文档中的请求参数名保持一致* @return*/@GetMapping("/emps")public Result page(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pageSize) {
// 设置默认值,但写法比较繁琐
// if(page == null) {page = 1;}
// if(pageSize == null) {pageSize = 10;}// 记录日志log.info("分页查询,参数:{},{}",page,pageSize);// 调用service分页查询PageBean pageBean = empService.page(page,pageSize);// 响应return Result.success(pageBean);}
}
- @RequestParam(defaultValue="默认值") //设置请求参数默认值
EmpService
package com.gch.service;import com.gch.pojo.PageBean;/**员工业务规则*/
public interface EmpService {/*** 条件分页查询* @param page => 分页查询的页码* @param pageSize => 分页查询的每页展示记录数* @return*/PageBean page(Integer page, Integer pageSize);
}
EmpServiceImpl
package com.gch.service.impl;import com.gch.mapper.EmpMapper;
import com.gch.pojo.Dept;
import com.gch.pojo.Emp;
import com.gch.pojo.PageBean;
import com.gch.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;/**员工业务实现类*/
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {@Autowiredprivate EmpMapper empMapper;/*** 分页查询* @param page => 分页查询的页码* @param pageSize => 分页查询的每页展示记录数* @return*/@Overridepublic PageBean page(Integer page, Integer pageSize) {// 1.获取总记录数Long total = empMapper.count();// 2.获取分页查询的数据列表List<Emp> rows = empMapper.pageSelect((page - 1) * pageSize,pageSize);// 3.封装PageBean对象return new PageBean(total,rows);}
}
EmpMapper
package com.gch.mapper;import com.gch.pojo.Emp;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;/**员工管理*/
@Mapper
public interface EmpMapper {/*** 查询总记录数* @return*/@Select("select count(*) from tlias.emp")public Long count();/*** 分页查询,获取数据列表/获取列表数据* @param startIndex => 起始索引* @param pageSize => 每页展示记录数* @return*/@Select("select * from tlias.emp limit #{startIndex},#{pageSize}")public List<Emp> pageSelect(Integer startIndex,Integer pageSize);}
PageBean
package com.gch.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;/**分页查询结果的封装类*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {/** 总记录数 */private Long total;/** 当前页数据列表 */private List rows;
}
3.1.1.5 功能测试
功能开发完成后,重新启动项目,使用Postman,发起GET请求:
3.1.1.6 前后端联调
打开浏览器,测试后端功能接口:
总结:
分页查询:
- 请求参数:页码、每页展示记录数
- 响应结果:总记录数 + 查询返回的数据列表 => PageBean
注解:
- 注解@RequestParam的属性defaultValue可以来设置参数的默认值!
3.1.2 分页插件{分页查询-PageHelper插件}
3.1.2.1 介绍
MyBatis框架当中分页查询的插件:PageHelper,通过这款插件就可以来简化分页查询的操作。
前面我们已经完了基础的分页查询,大家会发现:分页查询功能编写起来比较繁琐。
在Mapper接口中定义两个方法执行两条不同的SQL语句:
查询总记录数
查询获取指定页码的数据列表
在Service当中,调用Mapper接口的两个方法,分别获取:总记录数、查询结果列表,然后在将获取的数据结果封装到PageBean对象中。
大家思考下:在未来开发其他项目,只要涉及到分页查询功能(例:订单、用户、支付、商品),都必须按照以上操作完成功能开发
结论:手动实现的,原始方式的分页查询,存在着"步骤固定"、"代码繁琐"的问题 。
解决方案:可以使用一些现成的分页插件完成。对于Mybatis来讲现在最主流的就是PageHelper。
PageHelper是Mybatis的一款功能强大、方便易用的分页插件,支持任何形式的单表、多表的分页查询。
官网:
MyBatis 分页插件 PageHelper如果你也在用 MyBatis,建议尝试该分页插件,这一定是最方便使用的分页插件。分页插件支持任何复杂的单表、多表分页。https://pagehelper.github.io/
- 如果我们使用PageHelper这款分页插件来实现分页,我们程序员是不需要手动的去考虑分页的,所有与分页相关的操作插件已经帮我们完成了,所以我们只需要在Mapper接口当中正常的去执行查询就行(select * from xxx),不用考虑分页(limit、count(*)),所有与分页相关的操作都不用我们做,因为所有与分页相关的操作都是插件帮我们完成的。
在业务层,我们要基于PageHelper进行分页,主要涉及到三步操作:
- 需要调用PageHelper这个插件当中的提供的一个核心类PageHelper,调用PageHelper中的静态方法startPage(page,pageSize)来设置分页参数,告诉PageHelper我要查第几页,每页显示几条数据;
- 此时PageHelper会自动的对紧跟在其后的这条查询语句进行分页操作,查询完毕之后,可以把List集合强转为一个Page类型,这个Page类是PageHelper当中提供的,这个Page当中就封装了所有分页查询的结果,包括总记录数Total,包括结果列表Result;
- 接下来只需要把这两项封装到PageBean当中即可。
总结:如果我们使用PageHelper这个分页插件来进行分页查询,主要的步骤就是:
- 第一步:设置分页参数;
- 第二步:正常的执行查询,然后紧接着拿到查询结果之后把查询结果强转为Page类型;
- 第三步: 然后紧接着再从Page当中拿到分页查询的结果就可以了。
在执行empMapper.list()方法时,就是执行:select * from emp 语句,怎么能够实现分页操作呢?
分页插件帮我们完成了以下操作(PageHelper底层):
先获取到要执行的SQL语句:select * from emp并拦截
把SQL语句中的字段列表,变为:count(*),其实底层用的是count(0)
执行SQL语句:select count(*) from emp; // 获取到总记录数
再对要执行的SQL语句:select * from emp 进行改造,在末尾添加 limit ? , ?
执行改造后的SQL语句:select * from emp limit ? , ?
3.1.2.2 代码实现
- 当使用了PageHelper分页插件进行分页,就无需在Mapper中进行手动分页了,在Mapper中我们只需要进行正常的列表查询即可。
- 在Service层中,调用Mapper的方法之前设置分页参数,在调用Mapper方法执行查询之后,解析分页结果,并将结果封装到PageBean对象中返回。
1、在pom.xml引入依赖
<!-- PageHelper分页插件--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.2</version></dependency>
EmpController
package com.gch.controller;import com.gch.pojo.PageBean;
import com.gch.pojo.Result;
import com.gch.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/**员工管理控制器*/
@Slf4j
@RestController
@RequestMapping("")
public class EmpController {@Autowiredprivate EmpService empService;/*** 条件分页查询* @param page => 分页查询的页码* @param pageSize => 分页查询的每页展示记录数* 默认值的设置可以通过注解@RequestParam中的defaultValue()属性来指定默认值* 注意:形参page与pageSize需要于接口文档中的请求参数名保持一致* @return*/@GetMapping("/emps")public Result page(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pageSize) {
// 设置默认值,但写法比较繁琐
// if(page == null) {page = 1;}
// if(pageSize == null) {pageSize = 10;}// 记录日志log.info("分页查询,参数:{},{}",page,pageSize);// 调用service分页查询PageBean pageBean = empService.page(page,pageSize);// 响应return Result.success(pageBean);}
}
EmpService
package com.gch.service;import com.gch.pojo.PageBean;/**员工业务规则*/
public interface EmpService {/*** 条件分页查询* @param page => 分页查询的页码* @param pageSize => 分页查询的每页展示记录数* @return*/PageBean page(Integer page, Integer pageSize);
}
3、EmpServiceImpl
package com.gch.service.impl;import com.gch.mapper.EmpMapper;
import com.gch.pojo.Emp;
import com.gch.pojo.PageBean;
import com.gch.service.EmpService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;/**员工业务实现类*/
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {@Autowiredprivate EmpMapper empMapper;/*** 基于PageHelper分页插件实现分页查询* @param page => 分页查询的页码* @param pageSize => 分页查询的每页展示记录数* @return*/@Overridepublic PageBean page(Integer page,Integer pageSize){// 1.设置分页参数PageHelper.startPage(page,pageSize);// 2.执行查询List<Emp> empList = empMapper.list();// 获取分页结果Page<Emp> p = (Page<Emp>)empList;// 3.封装PageBean对象return new PageBean(p.getTotal(),p.getResult());}
}
2、EmpMapper
package com.gch.mapper;import com.gch.pojo.Emp;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;/**员工管理*/
@Mapper
public interface EmpMapper {/*** 基于PageHelper进行员工信息分页查询* @return*/@Select("select * from tlias.emp")public List<Emp> list();
}
3.1.2.3 测试
功能开发完成后,我们重启项目工程,打开Postman,发起GET请求,访问 :http://localhost:8080/emps?page=1&pageSize=5
后端程序SQL输出:
补充:分页插件的两个重要参数:
-
helperDialect
:分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置helperDialect
属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:oracle
,mysql
,mariadb
,sqlite
,hsqldb
,postgresql
,db2
,sqlserver
,informix
,h2
,sqlserver2012
,derby
特别注意:使用 SqlServer2012 数据库时,需要手动指定为sqlserver2012
,否则会使用 SqlServer2005 的方式进行分页。你也可以实现AbstractHelperDialect
,然后配置该属性为实现类的全限定名称即可使用自定义的实现方法。 -
reasonable
:分页合理化参数,默认值为false
。当该参数设置为true
时,pageNum<=0
时会查询第一页,pageNum>pages
(超过总数时),会查询最后一页。默认false
时,直接根据参数进行查询。
在application.properties中配置PageHelper分页插件:
#PageHelper分页插件的配置
#配置数据库方言
pagehelper.helper-dialect=mysql
#分页合理化参数配置
pagehelper.reasonable=true
总结:在MyBatis当中实现分页查询的两种方式:
- 手动实现分页查询
- 基于PageHelper分页插件实现分页查询
在项目开发当中,我们都是基于PageHelper分页插件实现分页查询,因为实现起来更加简洁,开发起来更加高效!
3.2 分页查询(带条件)
完了分页查询后,下面我们需要在分页查询的基础上,添加条件。
我们看到页面原型及需求中描述,搜索栏的搜索条件有三个,分别是:
-
姓名:模糊匹配
-
性别:精确匹配
-
入职日期:范围匹配
-- 条件分页查询(分页插件会自动帮我们做分页操作,因此不用写limit)
select *
from emp
where name like concat('%', '?', '%') -- 条件1:根据姓名模糊匹配and gender = ? -- 条件2:根据性别精准匹配and entrydate between '?' and '?' -- 条件3:根据入职日期范围查询
order by update_time desc;
而且上述的三个条件,都是可以传递,也可以不传递的,也就是动态的。 我们需要使用前面学习的Mybatis中的动态SQL 。
3.2.2 条件分页查询 - 思路分析
注意:在项目开发当中尽量少使用基本数据类型,而是使用包装类,因为基本类型有默认值!
- 用@DateTimeFormat注解中的pattern属性指定日期时间类型的格式!
3.2.3 功能开发
通过查看接口文档:员工列表查询
请求路径:/emps
请求方式:GET
请求参数:
参数名称 | 是否必须 | 示例 | 备注 |
---|---|---|---|
name | 否 | 张 | 姓名 |
gender | 否 | 1 | 性别 , 1 男 , 2 女 |
begin | 否 | 2010-01-01 | 范围匹配的开始时间(入职日期) |
end | 否 | 2020-01-01 | 范围匹配的结束时间(入职日期) |
page | 是 | 1 | 分页查询的页码,如果未指定,默认为1 |
pageSize | 是 | 10 | 分页查询的每页记录数,如果未指定,默认为10 |
在原有分页查询的代码基础上进行改造:
EmpController
package com.gch.controller;import com.gch.pojo.PageBean;
import com.gch.pojo.Result;
import com.gch.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.time.LocalDate;/**员工管理控制器*/
@Slf4j
@RestController
@RequestMapping("")
public class EmpController {@Autowiredprivate EmpService empService;/*** 条件分页查询* @param page 分页查询的页码* @param pageSize 分页查询的每页展示记录数* @param name 姓名* @param gender 性别* @param begin 入职日期的开始时间* @param end 入职日期的结束时间* 默认值的设置可以通过注解@RequestParam中的defaultValue()属性来指定默认值* 用@DateTimeFormat注解中的pattern属性指定日期时间类型的格式* 注意:方法签名上的形参变量名需要于接口文档中的请求参数名保持一致* @return*/@GetMapping("/emps")public Result page(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pageSize,String name, Short gender,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {// 记录日志log.info("条件分页查询,参数:page:{},pageSize:{},name:{},gender:{},begin:{},end:{}",page,pageSize,name,gender,begin,end);// 调用service分页查询PageBean pageBean = empService.page(page,pageSize,name,gender,begin,end);// 响应return Result.success(pageBean);}
}
EmpService
package com.gch.service;import com.gch.pojo.PageBean;import java.time.LocalDate;/**员工业务规则*/
public interface EmpService {/*** 条件分页查询* @param page => 分页查询的页码* @param pageSize => 分页查询的每页展示记录数* @param name => 姓名* @param gender => 性别* @param begin => 入职日期的开始时间* @param end => 入职日期的结束时间* @return*/PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end);
}
EmpServiceImpl
package com.gch.service.impl;import com.gch.mapper.EmpMapper;
import com.gch.pojo.Emp;
import com.gch.pojo.PageBean;
import com.gch.service.EmpService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDate;
import java.util.List;/**员工业务实现类*/
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {@Autowiredprivate EmpMapper empMapper;/*** 基于PageHelper分页插件实现分页查询* @param page => 分页查询的页码* @param pageSize => 分页查询的每页展示记录数* @param name => 姓名* @param gender => 性别* @param begin => 入职日期的开始时间* @param end => 入职日期的结束时间* @return*/@Overridepublic PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end){// 1.设置分页参数PageHelper.startPage(page,pageSize);// 2.执行条件分页查询List<Emp> empList = empMapper.list(name,gender,begin,end);// 获取条件分页查询结果Page<Emp> p = (Page<Emp>)empList;// 3.封装PageBean对象并返回return new PageBean(p.getTotal(),p.getResult());}
}
EmpMapper
package com.gch.mapper;import com.gch.pojo.Emp;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.time.LocalDate;
import java.util.List;/**员工管理*/
@Mapper
public interface EmpMapper {/*** 基于PageHelper进行员工信息条件分页查询* 查询条件参数:* @param name => 姓名* @param gender => 性别* @param begin => 入职日期的开始时间* @param end => 入职日期的结束时间* @return*/public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
}
EmpMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gch.mapper.EmpMapper"><!-- 动态条件查询操作--><select id="list" resultType="com.gch.pojo.Emp">select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_timefrom tlias.emp<where><if test="name != null and name != ''">name like concat('%', #{name}, '%')</if></where><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if>order by update_time desc</select>
</mapper>
3.2.4 功能测试
功能开发完成后,重启项目工程,打开Postman,发起GET请求:
控制台SQL语句:
3.2.5 前后端联调
打开浏览器,测试后端功能接口:
3.3 删除员工
查询员完成之后,我们继续开发新的功能:删除员工。
3.3.1 需求
当我们勾选列表前面的复选框,然后点击 "批量删除" 按钮,就可以将这一批次的员工信息删除掉了;也可以只勾选一个复选框,仅删除一个员工信息。
问题:我们需要开发两个功能接口吗?一个删除单个员工,一个删除多个员工
答案:不需要。 只需要开发一个功能接口即可(删除多个员工包含只删除一个员工)
- 删除单条记录可以理解为是一种特殊的批量删除,只不过这个批量删除里面只有一个。
3.3.2 接口文档
删除员工
- 基本信息
- 请求参数
参数格式:路径参数
参数说明:
- 响应数据
参数格式:application/json
参数说明:
3.3.3 思路分析
接口文档规定:
前端请求路径:/emps/{ids}
前端请求方式:DELETE
问题1:怎么在controller中接收请求路径中的路径参数?
@PathVariable
问题2:如何限定请求方式是delete?
@DeleteMapping
问题3:在Mapper接口中,执行delete操作的SQL语句时,条件中的id值是不确定的是动态的,怎么实现呢?
Mybatis中的动态SQL:foreach
- 一旦见到路径参数,马上想到@PathVariable注解。
SQL语句:
-- 批量删除
delete from emp where id in(?,?,?);
3.3.4 功能开发
通过查看接口文档:删除员工
- 请求路径:/emps/{ids}
- 请求方式:DELETE
- 请求参数:路径参数 {ids}
响应数据:json格式
EmpController
package com.gch.controller;import com.gch.pojo.PageBean;
import com.gch.pojo.Result;
import com.gch.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;import java.time.LocalDate;
import java.util.List;/**员工管理控制器*/
@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {@Autowiredprivate EmpService empService;/*** 条件分页查询* @param page 分页查询的页码* @param pageSize 分页查询的每页展示记录数* @param name 姓名* @param gender 性别* @param begin 入职日期的开始时间* @param end 入职日期的结束时间* 默认值的设置可以通过注解@RequestParam中的defaultValue()属性来指定默认值* 用@DateTimeFormat注解中的pattern属性指定日期时间类型的格式* 注意:方法签名上的形参变量名需要于接口文档中的请求参数名保持一致* @return*/@GetMappingpublic Result page(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pageSize,String name, Short gender,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {// 记录日志log.info("条件分页查询,参数:page:{},pageSize:{},name:{},gender:{},begin:{},end:{}",page,pageSize,name,gender,begin,end);// 调用service分页查询PageBean pageBean = empService.page(page,pageSize,name,gender,begin,end);// 响应return Result.success(pageBean);}/*** 批量删除员工信息* @param ids 接收前端传递过来的路径参数id数组* @return*/@DeleteMapping("/{ids}")public Result delete(@PathVariable List<Integer> ids) {// 记录日志log.info("批量删除员工,ids:{}",ids);// 调用service批量删除empService.delete(ids);// 响应return Result.success();}
}
EmpService
package com.gch.service;import com.gch.pojo.PageBean;import java.time.LocalDate;
import java.util.List;/**员工业务规则*/
public interface EmpService {/*** 条件分页查询* @param page => 分页查询的页码* @param pageSize => 分页查询的每页展示记录数* @param name => 姓名* @param gender => 性别* @param begin => 入职日期的开始时间* @param end => 入职日期的结束时间* @return*/PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end);/*** 批量删除员工信息操作* @param ids 前端传递过来的路径参数id集合*/void delete(List<Integer> ids);
}
EmpServiceImpl
package com.gch.service.impl;import com.gch.mapper.EmpMapper;
import com.gch.pojo.Emp;
import com.gch.pojo.PageBean;
import com.gch.service.EmpService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.time.LocalDate;
import java.util.List;/**员工业务实现类*/
@Slf4j
@Service
public class EmpServiceImpl implements EmpService {@Autowiredprivate EmpMapper empMapper;/*** 基于PageHelper分页插件实现分页查询* @param page => 分页查询的页码* @param pageSize => 分页查询的每页展示记录数* @param name => 姓名* @param gender => 性别* @param begin => 入职日期的开始时间* @param end => 入职日期的结束时间* @return*/@Overridepublic PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end){// 1.设置分页参数PageHelper.startPage(page,pageSize);// 2.执行条件分页查询List<Emp> empList = empMapper.list(name,gender,begin,end);// 获取条件分页查询结果Page<Emp> p = (Page<Emp>)empList;// 3.封装PageBean对象并返回return new PageBean(p.getTotal(),p.getResult());}/*** 批量删除员工信息* @param ids 前端传递过来的路径参数id集合*/@Overridepublic void delete(List<Integer> ids) {empMapper.deleteById(ids);}
}
EmpMapper
package com.gch.mapper;import com.gch.pojo.Emp;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.time.LocalDate;
import java.util.List;/**员工管理*/
@Mapper
public interface EmpMapper {/*** 基于PageHelper进行员工信息条件分页查询* 查询条件参数:* @param name => 姓名* @param gender => 性别* @param begin => 入职日期的开始时间* @param end => 入职日期的结束时间* @return*/public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);/*** 批量删除员工信息* @param ids 前端传递过来的路径参数id集合*/void deleteById(List<Integer> ids);
}
EmpMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gch.mapper.EmpMapper"><!-- 动态条件查询操作--><select id="list" resultType="com.gch.pojo.Emp">select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_timefrom tlias.emp<where><if test="name != null and name != ''">name like concat('%', #{name}, '%')</if></where><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if>order by update_time desc</select><!-- 批量删除操作 (?,?,?)--><delete id="deleteById">delete from emp where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete>
</mapper>
3.3.5 功能测试
功能开发完成后,重启项目工程,打开Postman,发起DELETE请求:
控制台SQL语句:
3.3.6 前后端联调
打开浏览器,测试后端功能接口:
相关文章:

SpringBootWeb案例 Part 2
目录 3. 员工管理 3.1 分页查询 3.1.1 基础分页 3.1.1.1 需求分析 3.1.1.2 接口文档 3.1.1.3 思路分析 3.1.1.4 功能开发 PageBean 3.1.1.5 功能测试 3.1.1.6 前后端联调 3.1.2 分页插件{分页查询-PageHelper插件} 3.1.2.1 介绍 官网: 3.1.2.2 代码实…...

4.14 HTTPS 中 TLS 和 TCP 能同时握手吗?
目录 实现HTTPS中TLS和TCP同时握手的前提: 什么是TCP Fast Open? TLS v1.3 TCP Fast Open TLSv1.3 HTTPS都是基于TCP传输协议实现的,得先建立完可靠得TCP连接才能做TLS握手的事情。 实现HTTPS中TLS和TCP同时握手的前提: 1、…...

游戏开发服务器选型的横向对比
来源一个某乎的作者,貌似来自台湾 上篇介绍了go版本的游戏服务器,这篇介绍下其它语言版本: SkynetkbengineNoahGameFramePomeloPinusET使用的语言C/LuaCCNodejsTypeScriptC#概述云风前辈开源的框架mmo框架server一个快速的、可扩展的、分布…...

【android12-linux-5.1】【ST芯片】HAL移植后配置文件生成报错
根据ST官方源码移植HAL源码后,执行readme指示中的生成配置文件指令时报错ST_HAL_ANDROID_VERSION未定义之类,应该是编译环境参数问题。makefile文件中是自动识别配置的,参数不祥就会报错,这里最快的解决方案是查询确定自己android…...
基于深度神经网络的分类--实现与方法说明
1、分类系统的设计 采用神经网络进行分类需要考虑以下几个步骤: 数据预处理: 将数据特征参数和目标数据整理成合适的输入和输出形式,可以使用过去一段时间的数据作为特征,然后将未来的数据作为输出标签,进行分类问题的…...

Java“牵手”天猫商品快递费用API接口数据,天猫API接口申请指南
天猫平台商品快递费用接口是开放平台提供的一种API接口,通过调用API接口,开发者可以获取天猫商品的标题、价格、库存、商品快递费用,宝贝ID,发货地,区域ID,快递费用,月销量、总销量、库存、详情…...

哲讯科技携手无锡华启动SCM定制化项目,共谋数字化转型之路
无锡华光座椅弹簧有限公司启动SCM定制化项目 近日,无锡华光座椅弹簧有限公司顺利举行了SCM定制化项目的启动会。本次启动会作为该项目实施的重要里程碑,吸引了双方项目组核心成员的共同参与,并见证了项目的正式启动。 无锡华光座椅弹簧有限公…...

ModaHub魔搭社区:将图像数据添加至Milvus Cloud向量数据库中
将图像数据添加至向量数据库中 图像分割裁剪完成后,我们就可以将其添加至 Milvus Cloud 向量数据库中了。为了方便上手,本项目中使用了 Milvus Lite 版本,可以在 notebook 中运行 Milvus 实例。接下来,使用 PyMilvus 连接至 Milvus Lite 提供的默认服务器。 这一步骤中,…...

svn下载
Download | VisualSVN for Visual Studio svn下载...
为什么说es是近实时搜索
首先要理解es的存储结构: 一个index的数据,分散在多个shard(分片),一个分片又有很多segment(段),es是数据不可变模型,更新数据只是新增一个版本。 es是怎么写数据的? 每次写的时候,首先会写到…...
程序自动分析——并查集+离散化
在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。考虑一个约束满足问题的简化版本:假设 x1,x2,x3,… 代表程序中出现的变量,给定 n 个形如 xixj 或 xi≠xj 的变量相等/不等的约束条件,请判定是否可以分别为…...

Qt 获取文件图标、类型 QFileIconProvider
Qt中获取系统图标、类型是通过QFileIconProvider来实现的,具体如下: 一、Qt获取系统文件图标1、获取文件夹图标QFileIconProvider icon_provider;QIcon icon icon_provider.icon(QFileIconProvider::Folder);2、获取指定文件图标QFileInfo file_info(n…...

TopicExchange主题交换机
目录 一、简介 二、代码展示 父pom文件 pom文件 配置文件 config 生产者 消费者 测试 结果 一、简介 主题交换机,这个交换机其实跟直连交换机流程差不多,但是它的特点就是在它的路由键和绑定键之间是有规则的。 简单地介绍下规则࿱…...
A Survey on Large Language Models for Recommendation
本文是LLM系列的文章,针对《A Survey on Large Language Models for Recommendation》的翻译。 大模型用于推荐的综述 摘要1 引言2 建模范式和分类3 判别式LLM用于推荐4 生成式LLM用于推荐5 发现6 结论 摘要 大型语言模型(LLM)作为自然语言…...
Springboot 入门指南:控制反转和依赖注入的含义和实现方式
目录 一、什么是控制反转(IoC)? 二、什么是依赖注入(DI)? 三、如何在 springboot 中使用 IoC 和 DI? 总结 一、什么是控制反转(IoC)? 控制反转ÿ…...

使用Tampermonkey(篡改猴)向页面注入js脚本
一、Tampermonkey 简单介绍 Tampermonkey是一款浏览器插件,适用于Chrome、Microsoft Edge、Safari、Opera Next 和 Firefox。他允许我们自定义javascript给指定网页添加功能,或修改现有功能。也可以用来辅助调试,或去除网页广告等。 官网地…...
软考高级系统架构设计师系列之:论文典型试题写作要点和写作素材总结系列文章二
软考高级系统架构设计师系列之:论文典型试题写作要点和写作素材总结系列文章二 一、论基于DSSA的软件架构设计与应用1.论文题目2.写作要点和写作素材二、论信息系统建模方法1.论文题目2.写作要点和写作素材三、论高可靠性系统中软件容错技术的应用1.论文题目2.写作要点和写作素…...

【Linux】如何在linux系统重启或启动时执行命令或脚本(也支持docker容器内部)
如何在linux系统重启或启动时执行命令或脚本(也支持docker容器内部) 第一种:使用 systemd 服务单元在重启或启动时运行命令或脚本第二种:使用 /etc/rc.d/rc.local 文件在重启或启动时运行脚本或命令第三种:使用 cronta…...

医疗中心管理环境温湿度,这样操作就对了!
随着医疗技术的不断发展,越来越多的医疗设备对于稳定的工作环境要求越来越高,而环境温湿度是影响这些设备性能和可靠性的关键因素之一。 为了确保医疗设备的正常运行和患者的安全,医疗机构越来越倾向于采用精密空调监控系统来维护设备的稳定性…...

嵌入式系统存储体系
一、存储系统概述 主要分为三种:高速缓存(cache)、主存和外存。 二、高速缓存Cache 高速缓冲存储器中存放的是当前使用得最多得程序代码和数据,即主存中部分内容的副本,其本身无自己的地址空间。在嵌入式系统中Cac…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
ThreadLocal 源码
ThreadLocal 源码 此类提供线程局部变量。这些变量不同于它们的普通对应物,因为每个访问一个线程局部变量的线程(通过其 get 或 set 方法)都有自己独立初始化的变量副本。ThreadLocal 实例通常是类中的私有静态字段,这些类希望将…...

高分辨率图像合成归一化流扩展
大家读完觉得有帮助记得关注和点赞!!! 1 摘要 我们提出了STARFlow,一种基于归一化流的可扩展生成模型,它在高分辨率图像合成方面取得了强大的性能。STARFlow的主要构建块是Transformer自回归流(TARFlow&am…...
命令行关闭Windows防火墙
命令行关闭Windows防火墙 引言一、防火墙:被低估的"智能安检员"二、优先尝试!90%问题无需关闭防火墙方案1:程序白名单(解决软件误拦截)方案2:开放特定端口(解决网游/开发端口不通)三、命令行极速关闭方案方法一:PowerShell(推荐Win10/11)方法二:CMD命令…...