hello,好久不见,今天我们继续来学习tlias系统的员工管理实现,主要完成分页查询以及删除员工这两个功能的实现
员工管理
分页查询
分页查询
根据页面原型我们可以分析,我们既需要根据上面的条件对其进行动态查询,又需要对其进行分页,所以我们对其进行解析,分为两步,首先进行分页查询,然后在其基础上加入条件,完成条件分页查询。
由于员工的数据比较多,所以我们在页面中可能需要分页展示,在进行分页查询时,用户可以选择每页的展示记录数,同时用户也可以点击具体页码来选择查询的具体页数,这时就涉及到数据库中的分页查询,大家想一下,在mysql中,我们通过什么来进行分页查询呢?
答案是limit,我们需要在limit之后设置两个分页参数,话不多说,我们现在来看一下mysql的分页查询基本语法。
-- 分页查询语法 -- 参数1:起始索引 如果起始索引为0就代表我现在要从第一条数据开始查询 -- 参数2:查询返回记录数 如果我指定为5,就代表我要从第一条开始查,查询返回5条数据,即前五条数据
select * from emp limit 0,5;
对比上面,我们可以发现核心的两部分就是后面的参数
-- 查询第二页数据,每页展示5条记录
select * from emp limit 5,5;
-- 查询第三页数据,每页展示5条记录
select * from emp limit 10,5;
根据上面的例子,我们可以知道起始索引的计算公式
起始索引={页码-1} *每页展示记录数
根据上图我们可以发现需要我们用mysql获取的内容(√所示),每页展示记录数由前端向我们返回,而后面的页数则是总记录数除我们的每页展示记录数,然后再向上取整即可。那么总记录数如何获取呢?
我们可以利用count聚合函数来获取
select count(*) from emp;
最后,我们需要分析一下前后端传递的参数和数据都有哪些?
首先是前端,前端需要传递给后端的参数
- 当前页码:page
- 每页展示记录数:pageSize
那么进行分页查询时,后台需要给前端返回的数据
- 数据列表:list slect * form emp limit ?,?;
- 总记录数:total select count(*) from emp;
大家想一下,服务端给前端响应的数据最终不就是我们设置的方法controller方法的返回值吗?但一个方法只能有一个返回值,我们上述返回的数据是两个数据类型不同的数据,那么该怎么做呢?
我们只能将其封装起来,选择map集合或者是实体类对其进行封装。我们选择实体类进行封装,其具有两个属性,一个数据列表,一个总记录数。命名为pageBean
接下来,我们就要实施具体的功能了,首先分析思路
第一步,封装pagebean实体类
package com.ittaotao.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; //数据列表
}
我们需要明白,实体类中命名的属性需要和接口文档保持相一致,否则数据将无法传输过去
接下来,我们进行代码实现
首先,定义mapper接口,实现数据库连接查询操作
package com.ittaotao.mapper;
import com.ittaotao.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 emp;")
public Long count();
/**
* 分页查询获取列表数据
* @param start
* @param pageSize
* @return
*/
@Select("select * from emp limit #{start},#{pageSize};")
public List<Emp> page(Integer start, Integer pageSize);
}
接着,编写控制层代码
package com.ittaotao.controller;
import com.ittaotao.pojo.PageBean;
import com.ittaotao.pojo.Result;
import com.ittaotao.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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class EmpController {
@Autowired
private EmpService empService;
@GetMapping("/emps")
public Result page(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize){
//借助注解为page和pageSize设置默认值
// @RequestParam(defaultValue = "1") Integer page 如果前端没有设置参数,设置默认值为1
log.info("分页查询,参数:{}{}",page,pageSize);
//调用service分页查询
PageBean pageBean = empService.page(page,pageSize);
return Result.success(pageBean);
}
}
最后编写service代码,调用接口,封装对象
package com.ittaotao.service.impl;
import com.ittaotao.mapper.EmpMapper;
import com.ittaotao.pojo.Emp;
import com.ittaotao.pojo.PageBean;
import com.ittaotao.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Override
public PageBean page(Integer page, Integer pageSize) {
//1.获取总记录数
Long count = empMapper.count();
//2.获取分页查询结果列表
//起始索引公式
Integer start = (page - 1) * pageSize;
List<Emp> empList = empMapper.page(start, pageSize);
//3.封装PageBean对象
PageBean pageBean = new PageBean(count,empList);
return pageBean;
}
}
通过测试,我们发现拿到了前面的十条记录,可是我们并没有传递page和pageSize的值,为什么会得到十条记录呢?原因是在controller中我们对page和pageSize设置了默认值
我们可以在控制台中发现我们拿到了默认值,这也就验证了默认值生效了
我们重新设置参数的值
最后,进行前后端联调测试,可以发现,postman测试的十七条数据已经全部传过来了
最后,是分页查询的小结
上面是对分页查询的介绍,是否觉得功能比较繁琐?
分页查询插件
黑马的经典白学这不就来了吗,接下来介绍一款mybatis的分页查询插件PageHelper
通过该插件可以简化分页查询的操作
首先,我们需要使用startPage设置分页参数,然后,我们只需要正常执行查询就ok了
首先,引入pagehelper依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.4</version>
</dependency>
不同版本对应的jdk可能也不同,如果报错了先刷新,实在不行改一下版本号
接下来,我们直接定义mapper接口
/**
* 员工信息查询
* @return
*/
@Select("select * from emp")
public List<Emp> list();
接下来,编写service代码
注意,上方选择pageNum和pageSize两个参数的方法
@Override
public 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对象
PageBean pageBean = new PageBean(p.getTotal(),p.getResult());
return pageBean;
}
因为controller是与前端进行交互的,所以我们不需要进行改动
运行,如果发现控制台有pagehelper,说明该插件已经生效
最后,进行pagehelper的小结
分页条件查询
接下来,我们在分页查询的基础上加入条件。首先,我们需要先在mysql进行模糊匹配
-- 条件查询员工 -- 姓名、性别、入职时间
select *
from emp
where name like concat('%', '张', '%')
and gender = 1
and entrydate between '2000-01-01' and '2010-01-01'
order by update_time desc ;
然后我们分析一下整体的思路
当我们在界面中输入完(姓名、性别、入职开始时间以及入职结束时间),点击条件查询,我们就会进入到controller层,controller接收分页参数的同时也要接收查询的条件,然后在调用service时只需把查询条件传递给service,service调用mapper接口再把这四个条件参数传递过去。最后mapper根据传递进来的四个参数进行条件查询
接下来参照思路完成具体的代码实现
首先完成controller和service层代码的完善
、controller
package com.ittaotao.controller;
import com.ittaotao.pojo.PageBean;
import com.ittaotao.pojo.Result;
import com.ittaotao.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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
@Slf4j
@RestController
public class EmpController {
@Autowired
private EmpService empService;
@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) {
//借助注解为page和pageSize设置默认值
// @RequestParam(defaultValue = "1") Integer page 如果前端没有设置参数,设置默认值为1
log.info("分页查询,参数:{},{},{},{},{},{}", page, pageSize,name,gender,begin,end);
//调用service分页查询
PageBean pageBean = empService.page(page,pageSize,name,gender,begin,end);
return Result.success(pageBean);
}
}
注意:@DateTimeFormat注解是对时间的格式进行声明
service以及实现类的代码
package com.ittaotao.service;
import com.ittaotao.pojo.PageBean;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
/*
员工管理
*/
public interface EmpService {
/**
* 分页查询
* @param page
* @param pageSize
* @return
*/
PageBean page(Integer page, Integer pageSize,String name, Short gender, LocalDate begin, LocalDate end);
}
package com.ittaotao.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.ittaotao.mapper.EmpMapper;
import com.ittaotao.pojo.Emp;
import com.ittaotao.pojo.PageBean;
import com.ittaotao.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.List;
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Override
public 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对象
PageBean pageBean = new PageBean(p.getTotal(),p.getResult());
return pageBean;
}
}
最后,因为是动态查询,所以我们这次需要在xml声明里面进行sql语言的编写
首先,在mapper里面进行调用
/**
* 员工信息查询
* @return
*/
//@Select("select * from emp")
public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
xml中声明
<?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.ittaotao.mapper.EmpMapper">
<!--条件查询-->
<select id="list" resultType="com.ittaotao.pojo.Emp">
select *
from emp
<where>
<if test="name != null and name != ''">
name like concat('%', #{name}, '%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>
</mapper>
首先resource下定义与EmpMapper一样的目录,创建文件EmpMapper.xml
注意:首先到官网上找到约束,其次需要对mapper标签进行声明,拷贝mapper的路径,同样的,select标签也要定义id为mapper接口的方法名list,并且保持返回的类型一致(resultType单条记录所封装的类型:即emp实体类,所以直接拷贝这个实体类的全类名)
以上就是分页条件查询的代码编写了,对其进行前后端联调如下
删除员工
然后,我们来实现员工管理中删除员工这一功能
经过分析,我们在界面原型中发现,删除员工分为批量删除和单个删除,那么我们要开发两个接口么?可以是可以,但是我们考虑一下是否可以直接开发批量删除这个借口呢?答案一定是可以的,因为单个删除就是特殊的批量删除,只不过他删除的一批只有一个罢了。
分析完之后,我们来看一下这个接口的基本信息
接下来,我们先来完成sql语句的编写
-- 批量删除员工 --
delete from emp where id in (1,2,3);
然后,我们分析一下删除操作的思路
可以发现,删除员工还是比较容易的
依旧是同样的套路,只不过删除操作的controller层需要加上注解@deletemapping,由于是路径参数,所以需要在方法集前面加上一个路径参数@pathvariable
empmapper中执行动态sql需要一个foreach标签进行批量删除
接下来进行代码实现
首先是controller层
@DeleteMapping("/{ids}")
public Result delete(@PathVariable List<Integer> ids){
log.info("批量删除,ids:{}",ids);
empService.delete(ids);
return Result.success();
}
我们在最上方加入一个注解
@RequestMapping("/emps")
可以省略之后所有的mapping定义的emps
然后是service编写delete方法,以及对应的实现类
// service
void delete(List<Integer> ids);
//impl
@Override
public void delete(List<Integer> ids) {
empMapper.delete(ids);
}
最后是mapper接口以及xml的配置
<!-- 批量删除(1, 2, 3) -->
<delete id="delete">
delete
from emp
where id in ;
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
/**
* 批量删除
* @param ids
*/
void delete(List<Integer> ids);
以上所以就编写完成了,最后我们进行测试
额,我进行的测试报错了
不着急,我来康一康
OK,最后发现我在xml配置中in后面加了个,导致最后sql语句是
delete from emp where id in, (1,2,3);
更改完之后显示成功了,太粗心了
最后我们也发现我们图形化界面中的15,16,17也已经删除掉了
前端显示也只剩14条信息了,大家如果感兴趣可以在前端进行删除试一试前后端联调,我不在做演示
以上就是本次博客的全部内容了,如有问题,还请评论区多多指教!
下一节我们继续讲解员工管理的新增员工以及修改员工等功能