此文章中的例子是沿用上一篇文章http://www.cnblogs.com/EasonJim/p/7055499.html的Spring MVC集成的例子改装的。

MyBatis分页有以下方式实现:

一、内存分页,使用RowBounds类,但这种方式不推荐,基本不用,所以此方式集成省略。

二、自定义实现,代码量比较少,简单,比较灵活。以下为具体的集成步骤:

1、在User.xml中加入select节点,并组装分页SQL

    <select id="getUserArticlesByLimit" parameterType="int" resultMap="resultUserArticleList">
select user.id,user.userName,user.userAddress,article.id as aid,article.title,article.content from user,article where user.id=article.userid and user.id=#{arg0} limit #{arg1},#{arg2}
</select>

注意:上面的写法中select节点的parameterType属性为int类型,而此时是由于当前业务的SQL语句就是全部都是int型的,当对于多类型时,这种属性就不能这么设置了。具体的在多参数中会进行讲解。

2、在IUserOperation.java中加入Mapping对应的方法

public List<Article> getUserArticlesByLimit(int id,int start,int limit);

3、修改UserController.java中获取数据的方法,改成分页方法,并传入指定参数

package com.jsoft.testmybatis.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import com.jsoft.testmybatis.inter.IUserOperation;
import com.jsoft.testmybatis.models.Article; @Controller
@RequestMapping("/article")
public class UserController {
@Autowired
IUserOperation userMapper; @RequestMapping("/list")
public ModelAndView listall(HttpServletRequest request,HttpServletResponse response){
List<Article> articles=userMapper.getUserArticlesByLimit(1,0,2);
ModelAndView mav=new ModelAndView("/article/list");
mav.addObject("articles",articles);
return mav;
}
}

意思是获取用户1的数据,从第0行开始的2条数据。

4、运行测试

mvn tomcat7:run

三、通过自定义插件的形式实现分页,也是最好的,也叫做分页拦截器。实现步骤如下:

插件支持MySQL和Oracle两种数据库,通过方法名关键字ListPage去匹配,有才进行分页处理,并且不用在Mapping中写分页代码。

1、在User.xml中添加查询语句

    <!-- 插件式分页查询测试 -->
<select id="selectArticleListPage" resultMap="resultUserArticleList">
select user.id,user.userName,user.userAddress,article.id as aid,article.title,article.content from user,article where user.id=article.userid and user.id=#{userid}
</select>

2、在IUserOperation.java中添加接口

    public List<Article> selectArticleListPage(
@Param("page")
PageInfo page,
@Param("userid")
int userid);

3、以下是插件实现的三个类

PageInfo.java:

package com.jsoft.testmybatis.util;

import java.io.Serializable;

public class PageInfo implements Serializable {

    private static final long serialVersionUID = 587754556498974978L;

    // pagesize ,每一页显示多少
private int showCount = 3;
// 总页数
private int totalPage;
// 总记录数
private int totalResult;
// 当前页数
private int currentPage;
// 当前显示到的ID, 在mysql limit 中就是第一个参数.
private int currentResult;
private String sortField;
private String order; public int getShowCount() {
return showCount;
} public void setShowCount(int showCount) {
this.showCount = showCount;
} public int getTotalPage() {
return totalPage;
} public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
} public int getTotalResult() {
return totalResult;
} public void setTotalResult(int totalResult) {
this.totalResult = totalResult;
} public int getCurrentPage() {
return currentPage;
} public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
} public int getCurrentResult() {
return currentResult;
} public void setCurrentResult(int currentResult) {
this.currentResult = currentResult;
} public String getSortField() {
return sortField;
} public void setSortField(String sortField) {
this.sortField = sortField;
} public String getOrder() {
return order;
} public void setOrder(String order) {
this.order = order;
} }

ReflectHelper.java:

package com.jsoft.testmybatis.util;

import java.lang.reflect.Field;

public class ReflectHelper {
public static Field getFieldByFieldName(Object obj, String fieldName) {
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
return superClass.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
}
}
return null;
} /**
* Obj fieldName的获取属性值.
*
* @param obj
* @param fieldName
* @return
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static Object getValueByFieldName(Object obj, String fieldName) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field field = getFieldByFieldName(obj, fieldName);
Object value = null;
if (field != null) {
if (field.isAccessible()) {
value = field.get(obj);
} else {
field.setAccessible(true);
value = field.get(obj);
field.setAccessible(false);
}
}
return value;
} /**
* obj fieldName设置的属性值.
*
* @param obj
* @param fieldName
* @param value
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static void setValueByFieldName(Object obj, String fieldName, Object value) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field field = obj.getClass().getDeclaredField(fieldName);
if (field.isAccessible()) {
field.set(obj, value);
} else {
field.setAccessible(true);
field.set(obj, value);
field.setAccessible(false);
}
} }

PagePlugin.java:

package com.jsoft.testmybatis.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Properties; import javax.xml.bind.PropertyException; import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry; @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
public class PagePlugin implements Interceptor { private static String dialect = "";
private static String pageSqlId = ""; @SuppressWarnings("unchecked")
public Object intercept(Invocation ivk) throws Throwable { if (ivk.getTarget() instanceof RoutingStatementHandler) {
RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk.getTarget();
BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper.getValueByFieldName(statementHandler, "delegate");
MappedStatement mappedStatement = (MappedStatement) ReflectHelper.getValueByFieldName(delegate, "mappedStatement"); if (mappedStatement.getId().matches(pageSqlId)) {
BoundSql boundSql = delegate.getBoundSql();
Object parameterObject = boundSql.getParameterObject();
if (parameterObject == null) {
throw new NullPointerException("parameterObject error");
} else {
Connection connection = (Connection) ivk.getArgs()[0];
String sql = boundSql.getSql();
String countSql = "select count(0) from (" + sql + ") myCount";
System.out.println("总数sql 语句:" + countSql);
PreparedStatement countStmt = connection.prepareStatement(countSql);
BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), parameterObject);
setParameters(countStmt, mappedStatement, countBS, parameterObject);
ResultSet rs = countStmt.executeQuery();
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
countStmt.close(); PageInfo page = null;
if (parameterObject instanceof PageInfo) {
page = (PageInfo) parameterObject;
page.setTotalResult(count);
} else if (parameterObject instanceof Map) {
Map<String, Object> map = (Map<String, Object>) parameterObject;
page = (PageInfo) map.get("page");
if (page == null)
page = new PageInfo();
page.setTotalResult(count);
} else {
Field pageField = ReflectHelper.getFieldByFieldName(parameterObject, "page");
if (pageField != null) {
page = (PageInfo) ReflectHelper.getValueByFieldName(parameterObject, "page");
if (page == null)
page = new PageInfo();
page.setTotalResult(count);
ReflectHelper.setValueByFieldName(parameterObject, "page", page);
} else {
throw new NoSuchFieldException(parameterObject.getClass().getName());
}
}
String pageSql = generatePageSql(sql, page);
System.out.println("page sql:" + pageSql);
ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql);
}
}
}
return ivk.proceed();
} private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
Configuration configuration = mappedStatement.getConfiguration();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
PropertyTokenizer prop = new PropertyTokenizer(propertyName);
if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) {
value = boundSql.getAdditionalParameter(prop.getName());
if (value != null) {
value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
}
} else {
value = metaObject == null ? null : metaObject.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
if (typeHandler == null) {
throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId());
}
typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
}
}
}
} private String generatePageSql(String sql, PageInfo page) {
if (page != null && (dialect != null || !dialect.equals(""))) {
StringBuffer pageSql = new StringBuffer();
if ("mysql".equals(dialect)) {
pageSql.append(sql);
pageSql.append(" limit " + page.getCurrentResult() + "," + page.getShowCount());
} else if ("oracle".equals(dialect)) {
pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
pageSql.append(sql);
pageSql.append(") tmp_tb where ROWNUM<=");
pageSql.append(page.getCurrentResult() + page.getShowCount());
pageSql.append(") where row_id>");
pageSql.append(page.getCurrentResult());
}
return pageSql.toString();
} else {
return sql;
}
} public Object plugin(Object arg0) {
// TODO Auto-generated method stub
return Plugin.wrap(arg0, this);
} public void setProperties(Properties p) {
dialect = p.getProperty("dialect");
if (dialect == null || dialect.equals("")) {
try {
throw new PropertyException("dialect property is not found!");
} catch (PropertyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
pageSqlId = p.getProperty("pageSqlId");
if (dialect == null || dialect.equals("")) {
try {
throw new PropertyException("pageSqlId property is not found!");
} catch (PropertyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} }

4、在Configuration.xml中配置插件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias alias="PageInfo" type="com.jsoft.testmybatis.util.PageInfo" />
</typeAliases>
<plugins>
<plugin interceptor="com.jsoft.testmybatis.util.PagePlugin">
<property name="dialect" value="mysql" />
<property name="pageSqlId" value=".*ListPage.*" />
</plugin>
</plugins>
</configuration>

注意:这个插件定义了一个规则,也就是在mapper中SQL语句的id必须包含ListPage才能被拦截。否则将不会分页处理。

5、在UserController.java中添加测试的Controller

    @RequestMapping("/pagelist")
public ModelAndView pageList(HttpServletRequest request, HttpServletResponse response) {
int currentPage = request.getParameter("page") == null ? 1 : Integer.parseInt(request.getParameter("page"));
int pageSize = 3;
if (currentPage <= 0) {
currentPage = 1;
}
int currentResult = (currentPage - 1) * pageSize; System.out.println(request.getRequestURI());
System.out.println(request.getQueryString()); PageInfo page = new PageInfo();
page.setShowCount(pageSize);
page.setCurrentResult(currentResult);
List<Article> articles = userMapper.selectArticleListPage(page, 1); System.out.println(page); int totalCount = page.getTotalResult(); int lastPage = 0;
if (totalCount % pageSize == 0) {
lastPage = totalCount % pageSize;
} else {
lastPage = 1 + totalCount / pageSize;
} if (currentPage >= lastPage) {
currentPage = lastPage;
} String pageStr = ""; pageStr = String.format("<a href=\"%s\">上一页</a> <a href=\"%s\">下一页</a>", request.getRequestURI() + "?page=" + (currentPage - 1), request.getRequestURI() + "?page=" + (currentPage + 1)); // 制定视图,也就是list.jsp
ModelAndView mav = new ModelAndView("/article/pagelist");
mav.addObject("articles", articles);
mav.addObject("pageStr", pageStr);
return mav;
}

6、页面文件pagelist.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:forEach items="${articles}" var="item">
${item.id }--${item.title }--${item.content }<br />
</c:forEach>
<div style="padding:20px;">${pageStr}</div>
</body>
</html>

7、测试结果:

测试工程:https://github.com/easonjim/5_java_example/tree/master/mybatis/test7

MyBatis3-实现MyBatis分页的更多相关文章

  1. Java SSM框架之MyBatis3(三)Mybatis分页插件PageHelper

    引言 对于使用Mybatis时,最头痛的就是写分页,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真不想花双倍的时间写count和select ...

  2. Mybatis学习---Mybatis分页插件 - PageHelper

    1. Mybatis分页插件 - PageHelper说明 如果你也在用Mybatis,建议尝试该分页插件,这个一定是最方便使用的分页插件. 该插件目前支持Oracle,Mysql,MariaDB,S ...

  3. 轻量级封装DbUtils&Mybatis之三MyBatis分页

    MyBatis假分页 参考DefaultResultSetHandler的skipRows方法. 温馨提示:部分代码请参考轻量级封装DbUtils&Mybatis之一概要 解决方案 1)之前公 ...

  4. 基于Mybatis分页插件PageHelper

    基于Mybatis分页插件PageHelper 1.分页插件使用 1.POM依赖 PageHelper的依赖如下.需要新的版本可以去maven上自行选择 <!-- PageHelper 插件分页 ...

  5. MyBatis学习总结(17)——Mybatis分页插件PageHelper

    如果你也在用Mybatis,建议尝试该分页插件,这一定是最方便使用的分页插件. 分页插件支持任何复杂的单表.多表分页,部分特殊情况请看重要提示. 想要使用分页插件?请看如何使用分页插件. 物理分页 该 ...

  6. mybatis分页插件pageHelper简单实用

    工作的框架spring springmvc mybatis3 首先使用分页插件必须先引入maven依赖,在pom.xml中添加如下 <!-- 分页助手 --> <dependency ...

  7. Mybatis分页插件

    mybatis配置 <!-- mybatis分页插件 --> <bean id="pagehelper" class="com.github.pageh ...

  8. Mybatis分页和Spring的集成

    写了一个Mybatis分页控件,在这记录一下使用方式. 在Maven中加入依赖: ? 1 2 3 4 5 6 7 8 9 <dependencies>   ...     <depe ...

  9. mybatis分页插件以及懒加载

    1.   延迟加载 延迟加载的意义在于,虽然是关联查询,但不是及时将关联的数据查询出来,而且在需要的时候进行查询. 开启延迟加载: <setting name="lazyLoading ...

  10. Mybatis分页插件PageHelper的配置和使用方法

     Mybatis分页插件PageHelper的配置和使用方法 前言 在web开发过程中涉及到表格时,例如dataTable,就会产生分页的需求,通常我们将分页方式分为两种:前端分页和后端分页. 前端分 ...

随机推荐

  1. Error while uploading slice_4.apk : WARNING: linker: libhoudini.so has text relocations. This is wasting memory and prevents security hardening. Please fix.

    问题: android studio 2.4版本新建项目后老是编译不过,查看log报如下错误,最后发现关闭即时编译功能可以解决此问题.这也算是2.4测试版的bug吧 android - Error w ...

  2. [转]Multivariate Time Series Forecasting with LSTMs in Keras

    1. Air Pollution Forecasting In this tutorial, we are going to use the Air Quality dataset. This is ...

  3. P4887 第十四分块(前体) 莫队

    题意: 给你一个序列,每次询问l,r问多少个a[i]^a[j]有k个1,k固定. 序列长度1e5,a[i]<=2^14 时限1s,空间40M 题解: 个人其实开始没什么思路,看了题解也好久,题解 ...

  4. 【Asp.net入门3-02】使用jQuery-jQuery 入门

    下面的几小节将介绍jQuery的基础知识.如前所述,不可能仅仅通过一章的内容详细介绍jQuery, 但可以向你说明如何对HTML文档中的内容执行简单的操作,以及更重要的,如何逐步实现本书其他 部分的示 ...

  5. img、列表和table标签

    一.img图片 <body> <a href="https://www.fmtxt.com"> <img src="images/1.jpg ...

  6. R语言计算moran‘I

    R语言计算moran‘I install.packages("maptools")#画地图的包 install.packages("spdep")#空间统计,m ...

  7. [非常重要的总结] Linux C相关函数

    (1)字符测试函数 isalnum(测试字符是否为英文字母或数字) isalpha(测试字符是否为英文字母) isascii(测试字符是否为ASCII码字符) isblank(测试字符是否为空格字符) ...

  8. 两个button之间的间距如何去掉

    在外层加上一个父元素,设置font-size:0;即可. 两个按钮之间的间距如何去掉

  9. 逻辑控制之While循环控制器(While Controller)

    测试环境 apache-jmeter-3.0 1.   添加While Controller 右键线程组->添加->逻辑控制器->响应断言 2.   控制面板介绍 添加后,面板如下 ...

  10. Java编程思想 4th 第1章 对象导论

    所有编程语言都提供抽象机制. 面向对象编程似乎是一种很好的编程思想和方式,面向对象编程中的对象简洁描述是:对象具有状态.行为和标识.状态指的是数据存储,存储的数据能反应状态:行为指的是方法,方法表示对 ...