本文以user表为例来记录一种Mybatis单表分页查询实现。
文中关于扩展文件的内容请参考:Spring Boot整合Mybatis框架在扩展文件编写自己的sql语句
1、在扩展查询接口基类BaseMapperExt.java中定义单表查询接口,但是针对某张表一定要有对应的扩展Mapper类继承它,比如要实现user表分页查询,一定要有接口类UserMapperExt.java继承BaseMapperExt.java,然后还要有与之对应的UserMapperExt.xml,具体请看下文。
package com.beibei.doc.dao.base;
import java.util.List;
import com.beibei.doc.util.Page;
/**
* 扩展基类
* @author beibei
*
* @param 实体类
* @param 实体类对应的example类
*/
public interface BaseMapperExt {
/**
* 单表分页查询
* @param page
* 分页对象
* @return
* @throws Exception
*/
public List selectByExampleListPage(Page page);
}
2、让UserMapperExt类继承BaseMapperExt,并且将泛型设置为User, UserExample类
package com.beibei.doc.dao.user.ext;
import com.beibei.doc.dao.base.BaseMapperExt;
import com.beibei.doc.model.user.User;
import com.beibei.doc.model.user.UserExample;
public interface UserMapperExt extends BaseMapperExt {
}
3、在与UserMapperExt.java类对应的扩展文件UserMapperExt.xml中加入分页查询代码。
至此,我们已经在dao层有了分页查询的方法,接下来介绍怎么在业务层实现分页查询。
4、创建分页辅助类Page.java,这个类至关重要,基本上关于分页的核心逻辑都封装在这个类里。
package com.beibei.doc.util;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 分页辅助类
* @author beibei
*
* @param 查询结果对应的实体类
* @param 单表对应的example
*/
public class Page implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1959424260780112289L;
public Page() {
}
/**
* 初始化nextPage和limit
* @param param --分页查询参数map
*/
public Page(Map param) {
String limitStr = StringUtil.getStr(param.get("limit"));
if(!"".equals(limitStr)){
this.limit = StringUtil.getInt(param.get("limit"));
this.nextPage = StringUtil.getInt(param.get("nextPage"));
}
}
/** 每页默认显示数据条数 */
public static int defaultLimit = 20;
/**是否 distinct */
private boolean distinct = false;
/**
* 下一页码,如需要当前页码则该属性减1
*/
private int nextPage;
/**
* 每页显示记录数
*/
private Integer limit;
/**
* 起始记录,因为引用的时候不会调用其get方法,因此要通过调用
*/
private int start;
/**
* 排序
*/
private String orderBy;
/**
* 查询参数
*/
private String search;
/**
* example查询参数
*/
private E example;
/**
* 其它查询参数,适用于联表查询时候设置条件参数
*/
private Map map = new HashMap();
/**
* 记录总数
*/
private long total;
/**
* 总页数
*/
private int pages;
/**
* 查询结果列表
*/
private List list;
public boolean isDistinct() {
return distinct;
}
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
/**
* 获取下一页页码必须先初始化:nextPage、limit、total
* @return
*/
public int getNextPage() {
if(limit == null){
return 0;
}
if(nextPage*limit >= total){
return 0;
} else {
return nextPage+1;
}
}
public void setNextPage(int nextPage) {
this.nextPage = nextPage;
}
public Integer getLimit() {
return limit;
}
public void setLimit(Integer limit) {
this.limit = limit;
}
public int getStart() {
if(this.nextPage < 1){
this.nextPage = 1;
}
if(limit == null){
return 0;
}
this.start = (nextPage - 1) * limit;
return start;
}
/**
* 查询页起始记录,分页查询必须设置起始页
* @param start
*/
public void setStart(int start) {
this.start = start;
}
public String getOrderBy() {
return orderBy;
}
/**
*
* 设置排序方式
* 严格按照sql语句关键词 ORDER BY 后面的排序字段和顺序编写
* 例如:
* 以 username 和 age 两个字段的倒序排序,
* 应该给orderBy赋值 username DESC, age DESC
*
* @param order
*/
public void setOrderBy(String orderBy) {
if(orderBy != null){
orderBy = " " + orderBy + " ";//加空格
}
this.orderBy = orderBy;
}
public String getSearch() {
return search;
}
public void setSearch(String search) {
this.search = search;
}
public E getExample() {
return example;
}
public void setExample(E example) {
this.example = example;
}
/**
* 其它过滤参数,适用于个性化参数查询
* @return
*/
public Map getMap() {
return map;
}
/**
* 其它过滤参数,适用于个性化参数查询
* @param map
*/
public void setMap(Map map) {
this.map = map;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
/**
* 返回总页数
* @return
*/
public int getPages() {
this.pages = 1;
if(this.limit != null && limit > 0){
int a = (int) (this.total / this.limit);
int b = (int) (this.total % this.limit);
if(b > 0){
pages = a + 1;
} else {
pages = a;
}
}
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
/**
*
* 获取分页查询结果,数据结构如下
* {
* "total": 4, 数据总量
* "nextPage": 0, 下一页页码,没有下一页值为 0
* "limit": 3, 每页数量
* "list": [ 查询结果列表
*
* ]
* }
*
*
* @return
*/
public Map getPageData(){
Map data = new HashMap<>();
data.put("nextPage", this.getNextPage());
data.put("total", this.getTotal());
data.put("limit", this.getLimit());
data.put("list", this.getList());
return data;
}
@Override
public String toString() {
return "Page [distinct=" + distinct + ", limit=" + limit + ", start="
+ start + ", orderBy=" + orderBy + ", nextPage=" + nextPage
+ ", total=" + total + ", pages=" + pages
+ ", search=" + search + ", example=" + example + ", map="
+ map + "]";
}
}
5、在BaseService.java中加入单表分页查询接口的定义
/**
* 单表分页查询
* @param page
* @return
*/
public Page selectByExampleListPage(Page page);
/**
* 分页查询
* @param param
* @return
*/
public RespData selectListPage(Map param);
6、在BaseServiceImpl.java中实现selectByExampleListPage接口,在这里封装对dao层数据库查询。
@Autowired
protected BaseMapperExt baseMapperExt;
@Override
public Page selectByExampleListPage(Page page) {
//查询数据总数
Integer total = this.countByExample(page.getExample());
//设置数据总数
page.setTotal(total);
List list = this.baseMapperExt.selectByExampleListPage(page);
page.setList(list);
return page;
}
7、让UserService.java接口类继承BaseService.java
UserService.java
package com.beibei.doc.service.user;
import com.beibei.doc.model.user.User;
import com.beibei.doc.model.user.UserExample;
import com.beibei.doc.service.base.BaseService;
public interface UserService extends BaseService {
}
8、让UserServiceImpl.java类继承BaseServiceImpl.java,并且实现selectListPage接口。
package com.beibei.doc.service.user.impl;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.beibei.doc.dao.user.ext.UserMapperExt;
import com.beibei.doc.model.user.User;
import com.beibei.doc.model.user.UserExample;
import com.beibei.doc.model.user.UserExample.Criteria;
import com.beibei.doc.service.base.impl.BaseServiceImpl;
import com.beibei.doc.service.user.UserService;
import com.beibei.doc.util.Page;
import com.beibei.doc.util.RespData;
@Service
public class UserServiceImpl extends BaseServiceImpl implements UserService {
@Autowired
private UserMapperExt userMapperExt;
@Override
public RespData selectListPage(Map param) {
RespData data = new RespData();
//构建分页查询对象
Page page = new Page<>(param);
//设置查询条件
UserExample example = new UserExample();
Criteria criteria = example.createCriteria();
criteria.andAgeEqualTo(18);
//设置分页数据
page.setOrderBy("id desc");
page.setExample(example);
//执行查询提取结果
page = this.selectByExampleListPage(page);
Map result = page.getPageData();
data.setData(result);
return data;
}
}
至此,就可以在Controller中调用分页查询接口对user表数据进行分页查询了,特别注意两个参数:nextPage是查询页码,从1开始;limit是每页数量,如果不传会默认查询全部。
@RequestMapping(value="/list")
public RespData list(@RequestParam Map param){
RespData data = this.userService.selectListPage(param);
return data;
}
最后,文中各个文件目录结构如下图