Java具体怎么实现分页查询业务?

286 阅读5分钟

1.1 需求分析和设计

1.1.1 产品原型

系统中的员工很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般的系统中都会以分页的方式来展示列表数据。而在我们的分页查询页面中, 除了分页条件以外,还有一个查询条件 "员工姓名"。

查询员工原型:

image.png

业务规则

  • 根据页码展示员工信息
  • 每页展示10条数据
  • 分页查询时可以根据需要,输入员工姓名进行查询

2.1.2 接口设计

找到资料-->项目接口文档-->苍穹外卖-管理端接口.html

image.png

注意事项:

  • 请求参数类型为Query,不是json格式提交,在路径后直接拼接。/admin/employee/page?name=zhangsan
  • 返回数据中records数组中使用Employee实体类对属性进行封装。

1.2 代码开发

1.2.1 设计DTO类

根据请求参数进行封装,在sky-pojo模块中

package com.sky.dto;
​
import lombok.Data;
​
import java.io.Serializable;
​
@Data
public class EmployeePageQueryDTO implements Serializable {
​
    //员工姓名
    private String name;
​
    //页码
    private int page;
​
    //每页显示记录数
    private int pageSize;
​
}
​

1.2.2 封装PageResult

后面所有的分页查询,统一都封装为PageResult对象。

在sky-common模块

package com.sky.result;
​
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
​
import java.io.Serializable;
import java.util.List;
​
/**
 * 封装分页查询结果
 */
@Data //这是一个Lombok库提供的注解,它会自动为类生成getter和setter方法,以及equals、canEqual、hashCode、toString等方法。
@AllArgsConstructor //这是一个Lombok库提供的注解,它会自动为类生成一个包含所有参数的构造函数。
@NoArgsConstructor //这是一个Lombok库提供的注解,它会自动为类生成一个无参构造函数。
public class PageResult implements Serializable {
​
    private long total; //总记录数
​
    private List records; //当前页数据集合
​
}
​

员工信息分页查询后端返回的对象类型为: Result

package com.sky.result;
​
import lombok.Data;
​
import java.io.Serializable;
​
/**
 * 后端统一返回结果
 * @param <T>
 */
@Data
public class Result<T> implements Serializable {
​
    private Integer code; //编码:1成功,0和其它数字为失败
    private String msg; //错误信息
    private T data; //数据
​
    public static <T> Result<T> success() {
        Result<T> result = new Result<T>();
        result.code = 1;
        return result;
    }
​
    public static <T> Result<T> success(T object) {
        Result<T> result = new Result<T>();
        result.data = object;
        result.code = 1;
        return result;
    }
​
    public static <T> Result<T> error(String msg) {
        Result result = new Result();
        result.msg = msg;
        result.code = 0;
        return result;
    }
​
}

1.2.3 Controller层

在sky-server模块中,com.sky.controller.admin.EmployeeController中添加分页查询方法。

    /**
     * 员工分页查询
     * @param employeePageQueryDTO
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("员工分页查询")
    //因为是查询功能,要包装返回数据所以用泛型,确定返回data的数据类型
    //DTO是前端往后端传递数据的封装,VO是后端传递给前端的封装
    //因为前端传过来的数据格式不是json而是Query,所以参数前不用加@RequestBody
    public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
        log.info("员工分页查询,参数为:{}", employeePageQueryDTO);
        PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);//后续Service层定义
        return Result.success(pageResult);
    }

1.2.4 Service层接口

在EmployeeService接口中声明pageQuery方法:

    /**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    //EmployeeService里的pageQuery返回的是PageResult类型
    PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

1.2.5 Service层实现类

在EmployeeServiceImpl中实现pageQuery方法:

    /**
     * 分页查询
     *
     * @param employeePageQueryDTO
     * @return
     */
    //1.接收一个EmployeePageQueryDTO对象作为参数,该对象包含了分页查询所需的信息,如当前页码(page)和每页显示的记录数(pageSize)。
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        // select * from employee limit 0,10 从第一条开始查一共查10条
        //开始分页查询
        //Pagehelper底层是ThreadLocal实现:先把page存到存储空间中,然后进行分页查询,分页查询之前,通过ThreadLocal把页码和每页记录数取出来,之后会动态地把limit关键字拼接进去,并且把页码和每页记录数动态算出来,最终构成完整的sql语句
        
        //2.调用PageHelper.startPage()方法,传入当前页码和每页显示的记录数,开始分页查询。
        PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());
        
        //3.在EmployeeMapper接口中定义一个名为pageQuery的方法,该方法接收一个EmployeePageQueryDTO对象作为参数,规定返回一个Page对象。在这个方法中,需要编写对应的动态SQL语句来实现分页查询功能。
        
        //4.调用employeeMapper.pageQuery(employeePageQueryDTO)方法,执行分页查询,得到一个Page对象。
        //这里的EmployeeMapper类的pageQuery方法未定义,需要去mployeeMapper.xml 中编写SQL
        //Mapper的pageQuery方法返回的是Page对象,但整个方法想返回的是PageResult对象
        Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
        //Page是PageHelper插件自带的一个类
​
        //5.从Page对象中获取总记录数(total)和当前页的记录列表(records)。
        long total = page.getTotal();
        List<Employee> records = page.getResult();
​
        //6.创建一个PageResult对象,将总记录数和当前页的记录列表作为参数传入,然后返回该对象
        return new PageResult(total, records);
    }

1.2.6 Mapper层

在 EmployeeMapper 中声明 pageQuery 方法:

    /**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    //Mapper里的pageQuery返回的是Page<Employee>类型
    //这里选择用动态sql而不用@Select注解
    //Page是PageHelper插件自带的一个类,PageHelper规定pageQuery要返回Page类泛型对象
    Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

在 src/main/resources/mapper/EmployeeMapper.xml 中编写SQL:

//定义了一个名为pageQuery的查询操作,其返回类型为com.sky.entity.Employee。
<select id="pageQuery" resultType="com.sky.entity.Employee">
        //编写动态sql
        select * from employee //这是一个简单的静态SQL查询,从employee表中选择所有列。
        <where>//这是一个动态SQL的开始标签,表示接下来的内容是动态条件
            //这是一个条件判断,如果name不为空且不为空字符串,则执行以下内容
            //name是员工的姓名,根据员工名字模糊分页查询
            <if test="name != null and name != ''">
                //这是一个动态SQL的条件,使用like关键字和concat函数来模糊匹配name列的值。#{name}是一个占位符,表示实际传入的参数值
                and name like concat('%',#{name},'%')
            </if>//这是动态SQL条件的结束标签。
        </where>
        order by create_time desc
    </select>//这是动态SQL的结束标签。