zoukankan      html  css  js  c++  java
  • MyBatis3-实现MyBatis分页

    此文章中的例子是沿用上一篇文章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

    参考:

    http://www.yihaomen.com/article/java/326.htm

  • 相关阅读:
    MY_0003:设置界面显示单位
    H5_0024:对于事先无法确定css大小的情况,可以通过JS动态修改
    H5_0023:html页面禁止放大缩小页面
    MY_0002:导出单位设置
    MY_0001:添加命令到自定义工具栏
    H5_0020:判断安卓苹果平台
    Web_0003:关于PHP上传文件大小的限制
    H5_0019:JS中定义json结构
    H5_0018:z-index失效的原因
    H5_0017:通过元素自定义属性值获取元素对象,并获取属性值
  • 原文地址:https://www.cnblogs.com/EasonJim/p/7056270.html
Copyright © 2011-2022 走看看