一.RowBounds
Mybatis提供了一个简单的逻辑分页使用类RowBounds,
- 逻辑分页:数据库返回的不是分页结果,而是全部数据,然后再由程序员通过代码获取分页数据
- 物理分页:依赖的是某一物理实体,这个物理实体就是数据库,比如MySQL数据库提供了limit关键字,程序员只需要编写带有limit关键字的SQL语句,数据库返回的就是分页结果。
逻辑分页主要用于数据量不大、数据稳定的场合,物理分页主要用于数据量较大、更新频繁的场合。
二.Mybatis-PageHelper
下面是我的使用总结:
- 首先我要实现 - 客户动态查询分页
数据字典表
CREATE TABLE `base_dict` (
`dict_id` varchar(32) NOT NULL COMMENT '数据字典id(主键)',
`dict_type_code` varchar(10) NOT NULL COMMENT '数据字典类别代码',
`dict_type_name` varchar(64) NOT NULL COMMENT '数据字典类别名称',
`dict_item_name` varchar(64) NOT NULL COMMENT '数据字典项目名称',
`dict_item_code` varchar(10) DEFAULT NULL COMMENT '数据字典项目代码(可为空)',
`dict_sort` int(10) DEFAULT NULL COMMENT '排序字段',
`dict_enable` char(1) NOT NULL COMMENT '1:使用 0:停用',
`dict_memo` varchar(64) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`dict_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
用户表
CREATE TABLE `customer` (
`cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
`cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
`cust_user_id` bigint(32) DEFAULT NULL COMMENT '负责人id',
`cust_create_id` bigint(32) DEFAULT NULL COMMENT '创建人id',
`cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
`cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
`cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
`cust_linkman` varchar(64) DEFAULT NULL COMMENT '联系人',
`cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
`cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',
`cust_zipcode` varchar(10) DEFAULT NULL,
`cust_address` varchar(100) DEFAULT NULL,
`cust_createtime` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`cust_id`),
KEY `FK_cst_customer_source` (`cust_source`),
KEY `FK_cst_customer_industry` (`cust_industry`),
KEY `FK_cst_customer_level` (`cust_level`),
KEY `FK_cst_customer_user_id` (`cust_user_id`),
KEY `FK_cst_customer_create_id` (`cust_create_id`)
) ENGINE=InnoDB AUTO_INCREMENT=162 DEFAULT CHARSET=utf8;
- 在model类Customer上创建包装类扩展CustomerQueryVo
public class CustomerQueryVo {
private String custName;
private String custSource;
private String custIndustry;
private String custLevel;
// 当前页码数
private Integer currentPage ;
// 每页显示数据条数
private Integer pageSize ;
- mapper层sql语句
这里resultMap="BaseResultMap"自定义,之前因为使用自动生成的model,导致使用resultType="customer"出现pagelist为null,但是page页数等存在且正确。
<sql id="customer_where">
<where>
<if test="custName != null and custName != ''">
and c.`cust_name` LIKE '%${custName}%'
</if>
<if test="custSource != null and custSource != ''">
AND c.`cust_source` = #{custSource}
</if>
<if test="custIndustry != null and custIndustry != ''">
AND c.`cust_industry` = #{custIndustry}
</if>
<if test="custLevel != null and custLevel != ''">
AND c.`cust_level` = #{custLevel}
</if>
</where>
</sql>
<select id="selectByPageCustomer" parameterType="com.wind.crm.model.CustomerQueryVo" resultMap="BaseResultMap">
SELECT
c.`cust_id`,
c.`cust_name`,
c.`cust_user_id`,
c.`cust_create_id`,
s.`dict_item_name` `cust_source`,
i.`dict_item_name` `cust_industry`,
l.`dict_item_name` `cust_level`,
c.`cust_linkman`,
c.`cust_phone`,
c.`cust_mobile`,
c.`cust_zipcode`,
c.`cust_address`,
c.`cust_createtime`
FROM `customer` c
LEFT JOIN base_dict s ON c.`cust_source`= s.`dict_id`
LEFT JOIN base_dict i ON c.`cust_industry` = i.`dict_id`
LEFT JOIN base_dict l ON c.`cust_level` = l.`dict_id`
<include refid="customer_where" />
</select>
- Service层使用PageHelper分页
我这里使用常用的方式startPage,这里我对PageInfo类的信息说明一下,看源码可能搞错逻辑。
PageInfo{pageNum=17, pageSize=6, size=6, startRow=97, endRow=102, total=141, pages=24,
list=Page{count=true, pageNum=17, pageSize=6, startRow=96, endRow=102, total=141, pages=24, reasonable=false, pageSizeZero=false}[com.wind.crm.model.Customer@2f92027],
prePage=16, nextPage=18, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true, navigatePages=8,
navigateFirstPage=13, navigateLastPage=20, navigatepageNums=[13, 14, 15, 16, 17, 18, 19, 20]}
navigatepageNums:当前显示页码
navigatePages:网页显示最大页码数量
public PageInfo<Customer> queryByPageCustomer(CustomerQueryVo vo) {
PageHelper.startPage(vo.getCurrentPage(), vo.getPageSize());
List<Customer> customers = customerMapper.selectByPageCustomer(vo);
//5为网页上显示的最大页数为5,即navigatePages,不是PageHelper里的pagesize 不设置默认为8
PageInfo<Customer> pageInfo = new PageInfo<Customer>(page,5);
}
-
Controller层直接调用,这里省略代码
-
jsp分页使用BootStrap,官网就有
<nav aria-label="Page navigation">
<ul class="pagination">
<c:if test="${pageInfo.hasPreviousPage}">
<li>
<a href="${pageContext.request.contextPath}/customer/list?currentPage=${pageInfo.prePage}&pageSize=${pageInfo.pageSize}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
</c:if>
<c:forEach items="${pageInfo.navigatepageNums}" var="nav">
<c:if test="${nav == pageInfo.pageNum}">
<li class="active"><a href="#">${nav}</a></li>
</c:if>
<c:if test="${nav != pageInfo.pageNum}">
<li><a href="${pageContext.request.contextPath}/customer/list?currentPage=${nav}&pageSize=${pageInfo.pageSize}">${nav}</a></li>
</c:if>
</c:forEach>
<c:if test="${pageInfo.hasNextPage}">
<li>
<a href="${pageContext.request.contextPath}/customer/list?currentPage=${pageInfo.nextPage}&pageSize=${pageInfo.pageSize}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</c:if>
</ul>
</nav>
- 结果