本文以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 <M> 實體類
* @param <E> 實體類對應的example類
*/
public interface BaseMapperExt<M, E> {
/**
* 單表分頁查詢
* @param page
* 分頁對象
* @return
* @throws Exception
*/
public List<M> selectByExampleListPage(Page<M, E> 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<User, UserExample> {
}
3、在與UserMapperExt.java類對應的擴展文件UserMapperExt.xml中加入分頁查詢代碼。
<?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="com.beibei.doc.dao.user.ext.UserMapperExt" >
<resultMap id="ExtResultMap" extends="com.beibei.doc.dao.user.UserMapper.BaseResultMap" type="com.beibei.doc.model.user.User" >
</resultMap>
<select id="selectByExampleListPage" resultMap="ExtResultMap" parameterType="com.beibei.doc.util.Page">
select
<include refid="com.beibei.doc.dao.user.UserMapper.Base_Column_List" />
from user
<if test="_parameter != null">
<include refid="com.beibei.doc.dao.user.UserMapper.Update_By_Example_Where_Clause" />
</if>
<if test="orderBy != null">
order by ${orderBy}
</if>
<if test="limit != null">
limit ${start} , ${limit}
</if>
</select>
</mapper>
至此,我們已經在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 <M> 查詢結果對應的實體類
* @param <E> 單表對應的example
*/
public class Page<M, E> implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1959424260780112289L;
public Page() {
}
/**
* 初始化nextPage和limit
* @param param --分頁查詢參數map
*/
public Page(Map<String, Object> 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<String, Object> map = new HashMap<String, Object>();
/**
* 記錄總數
*/
private long total;
/**
* 總頁數
*/
private int pages;
/**
* 查詢結果列表
*/
private List<M> 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;
}
/**
* <pre>
* 設置排序方式
* 嚴格按照sql語句關鍵詞 ORDER BY 后面的排序字段和順序編寫
* 例如:
* 以 username 和 age 兩個字段的倒序排序,
* 應該給orderBy賦值 username DESC, age DESC
* </pre>
* @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<String, Object> getMap() {
return map;
}
/**
* 其它過濾參數,適用于個性化參數查詢
* @param map
*/
public void setMap(Map<String, Object> 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<M> getList() {
return list;
}
public void setList(List<M> list) {
this.list = list;
}
/**
* <pre>
* 獲取分頁查詢結果,數據結構如下
* {
* "total": 4, 數據總量
* "nextPage": 0, 下一頁頁碼,沒有下一頁值為 0
* "limit": 3, 每頁數量
* "list": [ 查詢結果列表
*
* ]
* }
* </pre>
*
* @return
*/
public Map<String, Object> getPageData(){
Map<String, Object> 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<M, E> selectByExampleListPage(Page<M, E> page);
/**
* 分頁查詢
* @param param
* @return
*/
public RespData selectListPage(Map<String, Object> param);
6、在BaseServiceImpl.java中實現selectByExampleListPage接口,在這里封裝對dao層數據庫查詢。
@Autowired
protected BaseMapperExt<M, E> baseMapperExt;
@Override
public Page<M, E> selectByExampleListPage(Page<M, E> page) {
//查詢數據總數
Integer total = this.countByExample(page.getExample());
//設置數據總數
page.setTotal(total);
List<M> 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<User, UserExample> {
}
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<User, UserExample> implements UserService {
@Autowired
private UserMapperExt userMapperExt;
@Override
public RespData selectListPage(Map<String, Object> param) {
RespData data = new RespData();
//構建分頁查詢對象
Page<User, UserExample> 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<String, Object> result = page.getPageData();
data.setData(result);
return data;
}
}
至此,就可以在Controller中調用分頁查詢接口對user表數據進行分頁查詢了,特別注意兩個參數:nextPage是查詢頁碼,從1開始;limit是每頁數量,如果不傳會默認查詢全部。
@RequestMapping(value="/list")
public RespData list(@RequestParam Map<String, Object> param){
RespData data = this.userService.selectListPage(param);
return data;
}
最后,文中各個文件目錄結構如下圖