SpringBoot分页查询
**表示抽象的查询的行为,该查询将获得一个List集合**/}
一. spring boot简介
springboot特点:基于编程式和注解式配置,习惯(约定)优于配置。
springboot优势:
①:springboot让配置更简单
springboot推出了starter组件,即自动配置器,我们只需要在应用中引入相关组件的starter即可完成配置,从spring应用中复杂而繁琐的配置中解脱出来,实现项目的快速搭建。
springboot官方提供的starter命名格式为spring-boot-starter-×××
第三方提供的starter命名格式为×××-spring-boot-starter
②:springboot让开发更简单
springboot支持内嵌容器,如tomcat,jetty,应用自带服务器,直接启动应用即可,无需额外安装服务器。
springboot提供了强大的开发工具包,支持热启动。
③:springboot让测试更简单
springboot内置了常用的测试框架,仅需引入一个spring-boot-starter-test依赖包,即可进行各种测试
④:springboot让部署更加简单
springboot应用默认打包jar包
⑤:springboot让监控更简单
springboot就是一款自带监控的框架,专门提供了监控组件来完成这个工作。
眺望springcloud:
spring为应对互联网应用的要求(高可靠,高并发,能够负载均衡等),基于springboot推出了微服务框架springcloud,因此springcloud完全建立在springboot之上。
二. 开发一个springboot应用,引入依赖
<!--引入springboot父项目:该父项目中内置了很多习惯性配置和jar版本号之间的关联-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.4</version><!--此处版本号可以省略,因为springboot父项目中已经内置配置好了-->
</dependency>
<!--引入springboot开发工具包,可以支持热启动-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- 引入mybatis的starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!--引入springboot测试支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- pagehelper-spring-boot-starter -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
</dependencies>
<!--引入springboot构建插件,用于打包生成可执行jar文件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.4</version>
</plugin>
</plugins>
</build>
parent:spring-boot-starter-parent:引入springboot父项目:该父项目中内置了很多习惯性配置和jar版本号之间的关联
dependencies:
①:spring-boot-starter-web:web组件
②:spring-boot-devtools:引入springboot开发工具包,可以支持热启动
③:mybatis-spring-boot-starter
④:mysql-connector-java
⑤:spring-boot-starter-test:springboot测试组件
⑥:pagehelper-spring-boot-starter:分页组件
build:
spring-boot-maven-plugin:引入springboot构建插件,用于打包生成可执行jar文件
三. 开发springboot启动类
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//说明本应用为springboot应用,
// 而且还说明这是一个springboot的启动类,同时还说明这是一个配置类
//而且还是一个自动配置类
//主类所在的包,就是springboot应用的根包
//在springboot应用中,一般所有的组件如:controller,service,和dao等对象都应该在应用根包下或其子包下
@SpringBootApplication
//自动扫描映射器,并放入spring容器
@MapperScan("org.xupt.ygq.demo.dao")
public class MyApp {
public static void main(String[] args) {
//该语句为springboot应用的启动语句
SpringApplication.run(MyApp.class,args);
}
}
两个注解:
①:@SpringBootApplication:
说明本应用为springboot应用,而且还说明这是一个springboot的启动类,同时还说明这是一个配置类。
主类所在的包,就是springboot应用的根包,在springboot应用中,一般所有的组件如:controller,service,和dao,等对象都应该在应用根包或者根包的子包下面
②:@MapperScan:自动扫描映射器(也就是dao包),并存放在spring容器中
一条语句:
SpringApplication.run(MyApp.class,args);启动语句!!!
四. 配置application.properties资源文件
#配置内置服务器端口号,默认为8080
server.port=9999
#配置根日志的输出级别,默认为info
logging.level.root=info
#配置org.xupt.ygq.demo.dao包下的日志输出级别为trace,可以打印mybatis映射器执行结果
logging.level.org.xupt.ygq.demo.dao=trace
logging.level.org.xupt.ygq.demo=debug
#配置springmvc的日志
logging.level.web=trace
#配置数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/wddb
spring.datasource.username=root
spring.datasource.password=123456
#配置mybatis
#配置映射文件位置,在类路径下,mapper目录下的任意层级文件夹下的以.xml结尾的文件
mybatis.mapper-locations=classpath:mapper/**/*.xml
#pagehelper
#配置方言,即配置使用哪一个数据库
pagehelper.helper-dialect=mysql
#分页的合理化配置,即如果请求页码不合理时,自动合理化,比如:请求-9页,自动合理化成第一页
pagehelper.reasonable=true
五.因为要做分页查询,封装分页
5.1 分页类
import java.util.List;
public class Page<T> {
//当前页
private Integer current;
//首页
private Integer first;
//上页
private Integer pre;
//下页
private Integer next;
//尾页
private Integer last;
//每页最大记录数
private Integer pageSize;
//总记录数
private Long total;
//总页数
private Integer pages;
//当前页实际记录数
private Integer currSize;
//当前页数据记录
private List<T> list;
public Integer getCurrent() {
return current;
}
public void setCurrent(Integer current) {
this.current = current;
}
public Integer getFirst() {
return first;
}
public void setFirst(Integer first) {
this.first = first;
}
public Integer getPre() {
return pre;
}
public void setPre(Integer pre) {
this.pre = pre;
}
public Integer getNext() {
return next;
}
public void setNext(Integer next) {
this.next = next;
}
public Integer getLast() {
return last;
}
public void setLast(Integer last) {
this.last = last;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public Integer getPages() {
return pages;
}
public void setPages(Integer pages) {
this.pages = pages;
}
public Integer getCurrSize() {
return currSize;
}
public void setCurrSize(Integer currSize) {
this.currSize = currSize;
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
@Override
public String toString() {
return "Page{" +
"current=" + current +
", first=" + first +
", pre=" + pre +
", next=" + next +
", last=" + last +
", pageSize=" + pageSize +
", total=" + total +
", pages=" + pages +
", currSize=" + currSize +
", list=" + list +
'}';
}
}
类定义成泛型的:因为查询到的结果list,里面装的对象是什么,是不确定的。
5.2 分页参数
public class PageParam {
private Integer pageNum=1;//请求页码
private Integer pageSize=5;//每页最大记录数
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
}
在进行分页之前要先设置分页参数(包含两个属性,页码pageName和每页记录数pageSize)
PageHelper.startPage(pageParam);
5.3 分页查询api
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.xupt.ygq.demo.common.page.Page;
import org.xupt.ygq.demo.common.page.PageParam;
import org.xupt.ygq.demo.common.page.QueryAction;
import java.util.List;
public class Utils {
public static <T> Page<T> getPage(PageParam pageParam, QueryAction<T> queryAction){
//在查询之前设置分页参数,再执行查询和设置分页参数之间不能有其他的查询。
//该方法用于设置分页参数对象(含有页码pageName和每页记录数pageSize两个属性)
PageHelper.startPage(pageParam);
List<T> list = queryAction.executeQuery();//执行一个查询,获得List集合
//紧挨在查询之后构造分页信息对象
PageInfo<T> pageInfo = new PageInfo<>(list);
Page<T> page = new Page<>();
page.setCurrent(pageInfo.getPageNum());//当前页
page.setFirst(1);//首页
page.setPre(pageInfo.getPrePage());//上一页
page.setNext(pageInfo.getNextPage());//下一页
page.setLast(pageInfo.getPages());//最后一页
page.setPageSize(pageInfo.getPageSize());//每页最大记录数
page.setTotal(pageInfo.getTotal());//总记录数
page.setPages(pageInfo.getPages());//总页数
page.setCurrSize(pageInfo.getSize());//当前页实际记录数
page.setList(pageInfo.getList());//当前页数据记录
return page;
}
}
定义一个泛型生成分页对象的泛型类:(两个参数)
①:PageParame:声明分页参数,
②:QueryAction:一个查询行为的接口,表示要进行分页的查询行为
其中要注意分页信息对象:PageInfo:我们对于自己的分页对象的设置基于分页信息对象
最后返回一个分页对象:
5.4 定义抽象的查询行为
import java.util.List;
/*
* 表示抽象的查询的行为,该查询将获得一个List集合
* */
public interface QueryAction<T> {
public List<T> executeQuery();
}
5.5 封装返回结果
public class Result<T> {
public static final int CODE_OK = 200;
public static final int CODE_ERR_BUSINESS = 500;
public static final int CODE_ERR_SYS = 530;
public static final int CODE_ERR_UNLOGINED = 520;
public static <T>Result<T> ok(){
return new Result(true,CODE_OK,null,null);
}
public static <T>Result<T> ok(String message){
return new Result(true,CODE_OK,message,null);
}
public static <T>Result<T> ok(T data){
return new Result(true,CODE_OK,null,data);
}
public static <T>Result<T> ok(String message,T data){
return new Result(true,CODE_OK,message,data);
}
public static <T>Result<T> err(int errCode ,String message){
return new Result(false,errCode,message,null);
}
public static <T>Result<T> err(int errCode ,String message,T data){
return new Result(false,errCode,message,data);
}
private boolean success;//是否成功
private int code;//200 成功 500 业务失败,530 系统错误,520 未登录
private String message;//概要信息
private T data;
public Result(boolean success, int code, String message, T data) {
this.success = success;
this.code = code;
this.message = message;
this.data = data;
}
public boolean isSuccess() {
return success;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public T getData() {
return data;
}
}
六. 开发model和dto
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
public class Employee {
private String e_id;
private Integer d_id;//部门编号
private Integer e_sex;
private String e_name;
private Date e_birth;
public String getE_id() {
return e_id;
}
public void setE_id(String e_id) {
this.e_id = e_id;
}
public Integer getD_id() {
return d_id;
}
public void setD_id(Integer d_id) {
this.d_id = d_id;
}
public Integer getE_sex() {
return e_sex;
}
public void setE_sex(Integer e_sex) {
this.e_sex = e_sex;
}
public String getE_name() {
return e_name;
}
public void setE_name(String e_name) {
this.e_name = e_name;
}
//声明生成json的时间格式和时区
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT=8")
public Date getE_birth() {
return e_birth;
}
public void setE_birth(Date e_birth) {
this.e_birth = e_birth;
}
@Override
public String toString() {
return "Employee{" +
"e_id='" + e_id + '\'' +
", d_id=" + d_id +
", e_sex=" + e_sex +
", e_name='" + e_name + '\'' +
", e_birth=" + e_birth +
'}';
}
}
import java.util.Date;
//表示封装查询条件的dto
public class EmployeeQueryDto extends PageParam {
private String e_id;
private Integer d_id;//部门编号
private Integer e_sex;
private String e_name;
private Date e_birth_start;
private Date e_birth_end;
public String getE_id() {
return e_id;
}
public void setE_id(String e_id) {
this.e_id = e_id;
}
public Integer getD_id() {
return d_id;
}
public void setD_id(Integer d_id) {
this.d_id = d_id;
}
public Integer getE_sex() {
return e_sex;
}
public void setE_sex(Integer e_sex) {
this.e_sex = e_sex;
}
public String getE_name() {
return e_name;
}
public void setE_name(String e_name) {
this.e_name = e_name;
}
@DateTimeFormat(pattern = "yyyy-MM-dd")//对前端传来的时间格式说明
public Date getE_birth_start() {
return e_birth_start;
}
public void setE_birth_start(Date e_birth_start) {
this.e_birth_start = e_birth_start;
}
public Date getE_birth_end() {
return e_birth_end;
}
@DateTimeFormat(pattern = "yyyy-MM-dd")//对前端传来的时间格式说明
public void setE_birth_end(Date e_birth_end) {
this.e_birth_end = e_birth_end;
}
}
dto继承了PageParam:继承了他的分页参数,方便一起从前端页面传回数据。这样子就可以把dto和分页参数融合在一起进行参数传递。
七. 开发控制器组件
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.xupt.ygq.demo.common.Result;
import org.xupt.ygq.demo.common.page.Page;
import org.xupt.ygq.demo.dto.EmployeeQueryDto;
import org.xupt.ygq.demo.model.Employee;
import org.xupt.ygq.demo.service.EmpService;
@RestController
public class MyController {
@Autowired
private EmpService empService;
@GetMapping("/emp")
//分页查询需要分页参数,dto继承了分页参数类,所以他里面就有分页参数
public Result empList(EmployeeQueryDto dto){
Page<Employee> page = empService.getEmpPage(dto);
return Result.ok(page);
}
}
三个注解:
①:RestController
②:Autowired
③:GetMapping
定义处理方法:传递参数
八. 开发业务对象
import org.xupt.ygq.demo.common.page.Page;
import org.xupt.ygq.demo.common.page.PageParam;
import org.xupt.ygq.demo.model.Employee;
public interface EmpService {
public Page<Employee> getEmpPage(PageParam pageParam);
}
这里为什么用PageParam接受呢,因为dto对象时PageParam的子类,所以用父类型接收。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.xupt.ygq.demo.common.Utils;
import org.xupt.ygq.demo.common.page.Page;
import org.xupt.ygq.demo.common.page.PageParam;
import org.xupt.ygq.demo.dao.EmpDao;
import org.xupt.ygq.demo.model.Employee;
import org.xupt.ygq.demo.service.EmpService;
@Service//表示本对象是业务对象,并且受spring容器管理
@Transactional//声明本业务对象的所有方法都是事务性的
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpDao empDao;
/*
* pageHelper是一个适用于MyBatis的分页插件,通过该插件可以很方便的实现分页查询
* */
/*@Override
public Page<Employee> getEmpPage(PageParam pageParam) {
QueryAction<Employee> action = new QueryAction<Employee>() {
@Override
public List<Employee> executeQuery() {
return empDao.findEmpList();
}
} ;
return Utils.getPage(pageParam,action);
}*/
// @Override
// public Page<Employee> getEmpPage(PageParam pageParam) {
// QueryAction<Employee> action =()->{
// return empDao.findEmpList();
// };
//
// return Utils.getPage(pageParam,action);
// }
@Override
public Page<Employee> getEmpPage(PageParam pageParam) {
//QueryAction<Employee> action =()-> empDao.findEmpList();
return Utils.getPage(pageParam,()-> empDao.findEmpList(pageParam));
}
}
实现类里面有一个重要的点:就是调用分页查询api的时候,参数QueryAction接口的实现是内部类,再加上接口中只有一个方法,所以可以简化书写
九. 开发持久层
import org.xupt.ygq.demo.common.page.PageParam;
import org.xupt.ygq.demo.model.Employee;
import java.util.List;
public interface EmpDao {
//@Select("select * from t_emp")
public List<Employee> findEmpList(PageParam pageParam);
}
持久层返回的List在Service实现中被封装成了page对象。
十. 开发mapper
<?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="org.xupt.ygq.demo.dao.EmpDao">
<!-- 需求: 通过给定属性 查询用户 -->
<select id="findEmpList" resultType= "org.xupt.ygq.demo.model.Employee">
select * from t_emp
<where>
<!--<include refid="sql_query_where"></include>-->
<if test="e_id!=null and e_id!='' ">
and e_id like concat('%',#{e_id},'%')
</if>
<if test="e_name!=null and e_name!='' ">
and e_name like concat('%',#{e_name},'%')
</if>
<if test="e_sex!=null ">
and e_sex=#{e_sex}
</if>
<if test="d_id!=null ">
and d_id=#{d_id}
</if>
<if test="e_birth_start!=null ">
and e_date >= #{e_date_start}
</if>
<if test="e_birth_end!=null ">
and e_date <= #{e_date_end}
</if>
</where>
</select>
</mapper>
整个分页由插件完成!!!
mapper需要在application.properties中配置映射路径。
还需要注意映射的包:
十一. 测试
更多推荐
所有评论(0)