Mybatis单表分页查询

本文以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;
}

最后,文中各个文件目录结构如下图

Paste_Image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 33,603评论 18 399
  • 一. Java基础部分.................................................
    wy_sure阅读 9,298评论 0 11
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,183评论 19 139
  • 昨天结束了自己的2017研究生入学考试初试,走出考场的时候,自己蛮平静的,倒不是自己考的好,而且自己考的太差了,...
    hallelujah666阅读 1,558评论 0 2
  • 时代变了,你如何跟上节奏? 风口变了,你如何把握机遇? 玩法变了,你如何应对自如? 2017年的微商第一步我们要以...
    肖红千金阅读 3,142评论 0 0

友情链接更多精彩内容