在实现了分页查询后,我原本的项目之前的模糊查询失效,之前是传一个封装好的实体对象给后端,后端通过这个对象查询后返回结果给到前端。由于实现了分页,所以查询得到的结果也需要分页。
有个很关键的问题是分页需要传pageNum
和pageSize
这两个参数,后端@RequestBody
一次只能接收一个对象(@RequestBody
是读取的流的方式, 在取 body参数时第一个参数取到后把request.getInputStream()
关闭,一个请求中只包含一个request body)。而我要进行的查询又需要传一个对象,在走了一些弯路后想到:为什么不把pageNum和pageSize以及需要的实体整合成一个新的对象,传给后端后再分开获取值呢?这样虽然比较麻烦,但是没有其他思路我就这么试了,确实可以实现想要的多条件分页模糊查询。
后端实现
**注意:**要先导入PageHelper和Lombok插件,具体操作可以查看我的上一篇博客。
-
新建一个实体类
@Data @NoArgsConstructor public class FundPage { private String fundCode; private String fundFullName; private String custodianCode; private String fundCategory; private String needReview; private Integer pageNum; private Integer pageSize; }
-
dao层和mapper文件不需要更改,修改service层和实现类的业务函数
//原本的service层函数 List<FundInfo> getLots(FundInfo fundInfo) //改写后 PageInfo<FundInfo> getLots(FundInfo fundInfo,Integer pageNum,Integer pageSize); //service的实现类 @Override public PageInfo<FundInfo> getLots(FundInfo fundInfo,Integer pageNum,Integer pageSize) { FundInfoExample example = new FundInfoExample(); FundInfoExample.Criteria criteria = example.createCriteria(); if (fundInfo.getFundCode() != null) { criteria.andFundCodeLike("%" + fundInfo.getFundCode() + "%"); } if (fundInfo.getCustodianCode() != null) { criteria.andCustodianCodeLike("%" + fundInfo.getCustodianCode() + "%"); } if (fundInfo.getFundFullName() != null) { criteria.andFundFullNameLike("%" + fundInfo.getFundFullName() + "%"); } if (fundInfo.getNeedReview() != null) { criteria.andNeedReviewLike("%" + fundInfo.getNeedReview() + "%"); } if (fundInfo.getFundCategory() != null) { criteria.andFundCategoryLike("%" + fundInfo.getFundCategory() + "%"); } PageHelper.startPage(pageNum,pageSize); List<FundInfo> fundInfoList=fundInfoMapper.selectByExample(example); PageInfo<FundInfo> pageInfo=new PageInfo<>(fundInfoList); return pageInfo; }
这里使用了PageHelper中的PageInfo类,这里主要是用到了其中的几个方法。
注意:
PageHelper.startPage(pageNum,pageSize);
的作用开启分页,通过将查询后的结果集用PageInfo型的对象接收即可实现分页。此外,这里的模糊查询使用的是逆向工程生成的方法,具体可以查看我的其他博客。 -
controller层
@Autowired private FundInfoService fundInfoService; ... @PostMapping("/test") public Result<List<FundInfo>> getTest(@RequestBody FundPage fundPage){ FundInfo fundInfo=new FundInfo(); fundInfo.setNeedReview(fundPage.getNeedReview()); fundInfo.setFundCategory(fundPage.getFundCategory()); fundInfo.setFundCode(fundPage.getFundCode()); fundInfo.setFundFullName(fundPage.getFundFullName()); fundInfo.setCustodianCode(fundPage.getCustodianCode()); int pageNum=fundPage.getPageNum(); int pageSize=fundPage.getPageSize(); PageInfo<FundInfo> pageInfo=fundInfoService.getLots(fundInfo,pageNum,pageSize); List<FundInfo> fundInfoList=pageInfo.getList(); int total= Math.toIntExact(pageInfo.getTotal()); return Result.buildResult(Result.Status.OK,fundInfoList,total); }
controller层通过对获取到的
FundPage
的属性进行提取,提取到的fundInfo,pageNum,pageSize
作为调用模糊查询方法的参数。查询结果用PageInfo类型的对象接收,再定义一个FundInfo
类型的List
集合,调用PageInfo
的getList()
方法,最后通过工具类返回给前端。
前端实现
由于我是使用angular+primeng的来做前端,所以这里贴上我的页面布局,上面的部分是一个组件,下面的部分是一个组件(angular是组件化开发,可以理解为一个页面/部分是一个组件)
由于模糊查询提交的表单是在一个组件,显示结果在另一个组件,所以当中涉及到组件间传值的问题
-
我解决组件间传值的方法是在
fundInfoTable
组件中导入fundInfo
组件,然后再ngDoCheck()函数中监听表单是否提交ngDoCheck()是组件的生命周期的其中一部分,用于监测数据是否变更,但是每个变化检测周期都会大频率调用这个钩子,所以要轻量级实现,以下是官方文档的部分介绍
-
新建一个实体类,这实体类与后端是一致的。
export class FundPage { fundCode: string; fundFullName: string; fundCategory: string; custodianCode: string; needReview: string; pageNum:number; pageSize:number; }
-
将提交后的表单数据赋值给fundPage,并把pageNum和pageSize给个初始化值(null也行)
sub(data) { if (data.custodianCode == '') { data.custodianCode = null; } if (data.fundCategory == '') { data.fundCategory = null; } if (data.needReview == '') { data.needReview = null; } this.fundPage=data; this.fundPage.pageNum=1; this.fundPage.pageSize=10; }
这里省略了表单还有其他细节,主要也是说一个思路
-
在
fundInfoTable
组件定义监听变量//前两个用于控制懒加载的函数在ngDoCheck()中只被调用一次,没有控制的话会一直调用 bindOne: boolean = false; bindTwo: boolean = true; //用于区别对全部数据的分页查询和对模糊条件的分页查询 isSearch: boolean = false;
-
编写
ngDoCheck()
变更检测钩子ngDoCheck() { //当监听到查询值改变时,将监听值bindTwo赋值为true,使页面能够再次重新调用懒加载函数 if(this.fundPage!=this.fundInfoComponent.fundPage){ this.bindTwo=true; } // 检查是否提交了模糊查询服务 //通过两个变量来监听,使得this.loadFundInfos()只能调用一次 if (this.fundInfoComponent.fundPage&&(this.bindOne||this.bindTwo)) { this.fundPage = this.fundInfoComponent.fundPage; this.isSearch = true; this.bindTwo=false; this.loadFundInfos(); //查询后回到第一页 this.first=0 } }
-
懒加载函数
//懒加载分页的数据 loadFundInfos() { this.loading = true; setTimeout(() => { if (this.isSearch) { this.fundPage.pageNum = (this.first + 10) / 10; this.fundPage.pageSize = this.rows; this.fundService.getLots(this.fundPage) .then(response => { this.totalRecords = response.total; this.infos = response.data; }) } else { this.fundService.getPage(this.first + 10, this.rows) .then(response => { this.totalRecords = response.total; this.infos = response.data; }) } this.loading = false; }, 500) }
总结
后端的模糊查询分页其实难度不大,主要是前端卡了很久,主要问题在于如何把查询到的分页数据实时渲染到table上,试了几种钩子都没有效果,最后是突然想到之前做过的一道算法题,给我提供了用两个监听变量来控制函数的调用。我的实现方法可能不规范,但总归是实现了,希望能给大家一些思路,我是个新手,如果有错误的地方,欢迎大家指正,我们可以一起讨论!