查询员工操作

1:查询员工的接口设计:

查询员工

请求路径:/admin/employee/page

请求方式:GET

数据发送格式:Query

        name:员工姓名

        page:页码

        pagesize:每页记录数

数据返回格式:json

2:具体的代码实现:

接收前端传送过来的数据:

接收前端发送回来的数据:EmployeePageQueryDTO。

@Data
public class EmployeePageQueryDTO implements Serializable {

    //员工姓名
    private String name;

    //页码
    private int page;

    //每页显示记录数
    private int pageSize;

}

返回给前端的数据:Result(PageResult):

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {

    private long total; //总记录数

    private List records; //当前页数据集合

}

Controller层代码:

    /**
     * 分页查询员工操作
     * @param employeePageQueryDTO
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("分页查询员工")
    public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
        log.info("分页查询员工:{}",employeePageQueryDTO);
        PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);
        return Result.success(pageResult);
    }

这里提两个注意点把

        1:就是注意路径:需要在后面+/page

        2:注意返回的参数调用接口所传的参数(因为返回值有点套娃了)

Service层:

    /**
     * 分页查询员工
     * @param employeePageQueryDTO
     * @return
     */
    @Override
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        //select * from employee limit 0,10
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
        Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
        long total = page.getTotal();
        List<Employee> records = page.getResult();
        return new PageResult(total,records);
    }
这里的注意点就是这个PageHelper插件:

pagehelper是mybatis的一个插件,其作用是更加方便地进行分页查询

PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());

这一行主要是用来设置分页的页数和每页数量。相当于SQL语句中limit后面的两个参数。

注意:只有紧跟着PageHelper.startPage()的sql语句才被pagehelper起作用

Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);

使用了PageHelper返回值就得使用这个插件自己定义的返回值Page。

然后调用两个方法获取这个数量的总数和返回的数据。

        long total = page.getTotal();
        List<Employee> records = page.getResult();

Service层:

    /**
     * 分页查询员工
     * @param employeePageQueryDTO
     * @return
     */
    @Override
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        //select * from employee limit 0,10
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
        Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
        long total = page.getTotal();
        List<Employee> records = page.getResult();
        return new PageResult(total,records);
    }

Mapper层及动态SQL:

Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);
<mapper namespace="com.sky.mapper.EmployeeMapper">
    <select id="pageQuery" resultType="com.sky.entity.Employee">
        select * from sky_take_out.employee
        <where>
            <if test="name != null and name != ''">
                and name like concat('%',#{name},'%')
            </if>
        </where>
        order by create_time desc
    </select>
</mapper>

这里的的动态SQL:

需要回顾一下之前的Mybatis的动态SQL的知识:

 动态SQL:

随着用户的输入或外部条件的变化而变化的SQL语句,我们称为 动态SQL。

if标签:

<if>:用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。

先来看第一个代码案例:


<select id="list" resultType="com.springbootcrud.Pojo.Emp">
        select *
        from mybatis.emp
        where
            <if test="name!=null">
                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>

上面这段代码就可以解决查询的问题:比如你给我的测试条件是:
List<Emp> empList = empMapper.list("张", (short) 1, LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));
每个属性都有,那肯定没什么问题。
List<Emp> empList = empMapper.list("张",null,null,null);
但如果是下面这种,三个条件中只有一个存在,如果没有用if判断语句的话就会报错。

where标签:

<where>:where 元素只会在子元素有内容的情况下才插入where子句。而且会自动去除子句的开头的AND 或OR

第二个案例:

基于上面的if标签,我们已经解决了一部分的问题:
不过还是不够全面,仔细看
    <if test="name!=null">
                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>
中间有很多的and,这样会导致什么情况呢:
List<Emp> empList = empMapper.list(null,(short)1,null,null);
因为第一个条件不存在,所以导致后面的(short)1这个条件根本查不到,所以,也会报错
所以我们引入<where>标签,作用就是能去除开头的and和or,还有一个作用,如果where条件中的所有if都不成立,那这个where标签就不会定义
比如List<Emp> empList = empMapper.list(null,null,null,null);这种情况就会查询出所有的记录。

3:功能测试:

        这里的功能测试还是主要用Swagger方式来测试

小插曲:

这个小插曲的原因和JWT令牌过期有关系:

代码没有问题的情况下报了401的响应码,原因就是因为JWT令牌的时间过期了。

所以这个时候我们需要重新获取一个JWT令牌。

查询结果:

4:代码优化:

程序存在的问题:

仔细看前端页面展示的结果-----最后操作时间那一栏

时间的格式不太对,下面就来优化这个问题。

解决方法:

在 WebMvcConfiguration 中扩展Spring MVC的消息转换器,统一对日期类型进行格式化处理

扩展Spring MVC的消息转换器:

Spring MVC框架的消息转换器是用来处理请求和响应的数据格式转换的组件.
在SpringMVC中,java对象转JSON对象是通Jackson实现的,涉及到SpringMVC中的消息转换器MappingJackson2HttpMessageConverter.
当请求和响应的数据格式不匹配时,就需要对消息转换器功能进行拓展.

我们首先要在我们编写的 WebMvcConfiguration 类中继承 WebMvcConfigurationSupport(这个应该是写web相关程序都要继承的类,应该是SpringMVC那一块的东西)

        
    /**
     * 扩展Spring MVC的消息转化器
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器");
        //创建一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象转换成json数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转化器加入到容器中,并设置优先级
        converters.add(0,converter);
    }
在WebMvcConfiguration 类中重写 extendMessageConverters 方法:        

     1:创建一个消息转换器对象

MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

2:需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象转换成json数据
converter.setObjectMapper(new JacksonObjectMapper());

3:将自己的消息转化器加入到容器中,并设置优先级(0)
converters.add(0,converter);
对象转换器:

这个对象转换器是我们自己定义的:(比较固定的代码)

/**
 * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
 * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
 * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
 */
public class JacksonObjectMapper extends ObjectMapper {

    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    //public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }
}

这里主要提供的功能就是序列化和反序列化。

优化之后的效果图:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值