环境:Spring 4.2.1 Mybatis 3.2.8 pagehelper 5.1.2

Mybatis官方教程:https://github.com/pagehelper/Mybatis-PageHelper/blob/d5947437cc6272cb3f1b186cadee74f1f8072cbb/wikis/zh/HowToUse.md

  • 加入pageHelper依赖

      <dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.2</version>
    </dependency>
  • 在Mybatis-config.xml中配置pageHelper的拦截器

      <plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
    <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
    <property name="helperDialect" value="mysql" />
    <property name="reasonable" value="true" />
    <property name="supportMethodsArguments" value="true" />
    <property name="autoRuntimeDialect" value="true" /> </plugin> </plugins>
  • 调用startPage()分页方法,在获取数据后将数据放到PageInfo对象中。

      PageHelper.startPage(page, pageSize);
    List<Map<String, Object>> list = itemMapper.getItems();
    PageInfo<Map<String, Object>> pageInfor = new PageInfo<Map<String, Object>>(list);

即可对数据进行分页处理。

Mybatis使用pageHelper分页出现的问题

在pageHelper的文档中,我们可以看到这样的提示分页插件不支持嵌套结果映射https://github.com/pagehelper/Mybatis-PageHelper/blob/d5947437cc6272cb3f1b186cadee74f1f8072cbb/wikis/zh/Important.md),由于嵌套结果方式会导致结果集被折叠,因此分页查询的结果在折叠后总数会减少,所以无法保证分页结果数量正确。这时候对于一些嵌套查询来说使用通用pageHelper已经不能用了,因此需要我们通过手动分别查询分页数据以及分页数据的映射数据。

通过使用一个例子对pageHelper进行测试不兼容嵌套查询的结果映射:

	<resultMap type="java.util.Map" id="fatherMap">
<result column="orderId" property="orderId" />
<result column="payment" property="payment" />
<result column="buyer_nick" property="buyerNick" />
<result column="shipping_code" property="shippingCode" />
<result column="state" property="state" />
</resultMap> <resultMap type="java.util.Map" id="orderMap" extends="fatherMap"> <collection property="items" javaType="ArrayList" resultMap="itemMap" /> </resultMap> <select id="getOrdersByUserId" resultMap="orderMap"> SELECT o.order_id AS orderId,o.payment ,o.buyer_nick,o.shipping_code
,o.status AS orderState,i.title ,i.price FROM tb_order AS o,tb_item AS
i,tb_order_item AS oi WHERE o.user_id=#{userId} AND
oi.order_id=o.order_id AND i.id=oi.item_id </select> /*Service层代码*/
public List<Map<String, Object>> getOrdersByUserId(String userId) { PageHelper.startPage(1, 2);
List<Map<String, Object>> list = orderMapper.getOrdersByUserId(userId);
return list; }

通过嵌套查询返回一个Map对象并嵌套了另一个表中的多条数据(List集合),在取出数据后,可以看到这样的结果:

可以发现,pageHelper对我们的子数据进行了分页,我们要两条数据且只是出现了一条数据,这个时候,就只有通过分别查询来取出数据了。

首先,对订单数据不进行关联查询,先把数据取出来,然后根据取出来的订单对象,再把关联的信息查出来,这样就可以使用pageHelper来进行操作了。在Service层的代码如下:

	public List<Map<String, Object>> getAnotherOrdersByUserId(String userId) {
PageHelper.startPage(1, 2);
List<Map<String, Object>> orderMaps = orderMapper.getAnotherOrdersByUserId(userId);
for (Map<String, Object> map : orderMaps) {
String orderId = (String) map.get("orderId");
List<Map<String, Object>> items = orderMapper.getItems(orderId);
map.put("items", items);
}
PageInfo pageInfor = new PageInfo(orderMaps);
System.out.println(pageInfor.getPageNum());
System.out.println(pageInfor.getTotal()); return orderMaps;
}

mapper的代码:

<select id="getAnotherOrdersByUserId" resultMap="fatherMap">

	SELECT o.order_id AS orderId,o.payment ,o.buyer_nick,o.shipping_code
,o.status AS orderState FROM tb_order AS o WHERE o.user_id=#{userId} </select> <select id="getItems" resultMap="itemMap"> SELECT item.title ,item.price FROM tb_order_item AS oi ,tb_item AS item
WHERE oi.order_id=#{orderId} AND oi.item_id=item.id </select>

这样通过分别查询就可以避免了pageHelper的联合查询的问题。

正确的数据显示:

Demo:https://github.com/esileme/MybatisPager

PageHelper分页原理

在Mybatis中,提供了一个Interceptor接口,Mybatis的PageInterceptor类实现了Interceptor接口,在这个接口中,MyBatis允许我们拦截四个方法(ParameterHandler、ResultSetHandler、StatementHandler、Executor),可以对这四个方法进行拦截并实现相应的操作。

我们可以自定义实现Interceptor方式对Mybatis返回为Map的对象进行数据库数据与pojo对象映射的操作:

  • 在Mybatis-config.xml中配置

    <plugin interceptor="com.yl.page.intercpter.CameHumpIntercpter"></plugin>
  • code

    package com.yl.page.intercpter;
    
    import java.sql.Statement;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    import java.util.Set; import org.apache.ibatis.executor.resultset.ResultSetHandler;
    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; @Intercepts( @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class }))
    public class CameHumpIntercpter implements Interceptor { public Object intercept(Invocation invocation) throws Throwable {
    List<Object> values = (List<Object>) invocation.proceed();
    for (Object object : values) { if (object instanceof Map) {
    processMap((Map) object); } else {
    break;
    }
    }
    return values;
    } public Object plugin(Object target) { return Plugin.wrap(target, this);
    } // 获取配置参数
    public void setProperties(Properties properties) { } private void processMap(Map<String, Object> map) {
    Set<String> keySet = new HashSet<String>(map.keySet());
    for (String key : keySet) { if ((key.charAt(0) >= 'A' && key.charAt(0) <= 'Z') || key.indexOf("_") >= 0) { Object value = map.get(key);
    map.remove(key);
    map.put(undelineToNomall(key), value);
    }
    } } public String undelineToNomall(String inputString) {
    StringBuilder buder = new StringBuilder();
    boolean nextUpperCase = false;
    for (int i = 0; i < inputString.length(); i++) { char c = inputString.charAt(i);
    if (c == '_') {
    if (buder.length() > 0) {
    nextUpperCase = true;
    } } else { if (nextUpperCase) {
    buder.append(Character.toUpperCase(c)); nextUpperCase = false;
    } else {
    buder.append(Character.toLowerCase(c));
    } } } return buder.toString();
    } }

PageHelper在Mybatis中的使用的更多相关文章

  1. java使用插件pagehelper在mybatis中实现分页查询

    摘要: com.github.pagehelper.PageHelper是一款好用的开源免费的Mybatis第三方物理分页插件 PageHelper是国内牛人的一个开源项目,有兴趣的可以去看源码,都有 ...

  2. Mybatis中分页存在的坑1

    站在巨人的肩膀上 https://www.cnblogs.com/esileme/p/7565184.html 环境:Spring 4.2.1 Mybatis 3.2.8 pagehelper 5.1 ...

  3. [原创]关于mybatis中一级缓存和二级缓存的简单介绍

    关于mybatis中一级缓存和二级缓存的简单介绍 mybatis的一级缓存: MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候 ...

  4. 记录一次bug解决过程:mybatis中$和#的使用

    一.总结 mybatis中使用sqlMap进行sql查询时,经常需要动态传递参数.动态SQL是mybatis的强大特性之一,也是它优于其他ORM框架的一个重要原因.mybatis在对sql语句进行预编 ...

  5. mybatis中#{}与${}的差别(如何防止sql注入)

    默认情况下,使用#{}语法,MyBatis会产生PreparedStatement语句中,并且安全的设置PreparedStatement参数,这个过程中MyBatis会进行必要的安全检查和转义. # ...

  6. mybatis 中的where标签

    mybatis中的where标签可以去除 开头的 and 或者 or 但是放在后面的不行 失败的: <select id="countNotesByParam" parame ...

  7. Mybatis中SqlMapper配置的扩展与应用(3)

    隔了两周,首先回顾一下,在Mybatis中的SqlMapper配置文件中引入的几个扩展机制: 1.引入SQL配置函数,简化配置.屏蔽DB底层差异性 2.引入自定义命名空间,允许自定义语句级元素.脚本级 ...

  8. mybatis中使用使用模块化sql

    主要使用到mybatis中的标签 <sql id="tempId"> select * from student <sql> 使用的标签如下: <in ...

  9. “mybatis 中使用foreach 传

    为了帮助网友解决“mybatis 中使用foreach 传”相关的问题,中国学网通过互联网对“mybatis 中使用foreach 传”相关的解决方案进行了整理,用户详细问题包括:mybatismap ...

随机推荐

  1. MySql两种存储引擎的区别

    MyISAM是MySQL的默认数据库引擎(5.5版之前),由早期的ISAM(Indexed Sequential Access Method:有索引的顺序访问方法)所改良.虽然性能极佳,但却有一个缺点 ...

  2. 经典JS闭包面试题(来理解闭包)(转)

    转载地址:http://www.cnblogs.com/xxcanghai/p/4991870.html 先看代码: function fun(n,o) { console.log(o) return ...

  3. css3 自定义滚动条样式

    ::-webkit-scrollbar :滚动条整体部分 ::-webkit-scrollbar-thumb :滚动条里面的小方块样式 ::-webkit-scrollbar-track 滚动条的轨道 ...

  4. 整理oracle 树形查询

    注:本文参考了<整理oracle 树形查询> sql树形递归查询是数据库查询的一种特殊情形,也是组织结构.行政区划查询的一种最常用的的情形之一.下面对该种查询进行一些总结: create ...

  5. Oracle管理文件OMF (oracle managed files)

    简化dba的管理操作 1:启用 omf 23:16:04 SYS@orcl> show parameter DB_CREATE_FILE_DEST NAME TYPE VALUE ------- ...

  6. MySQL 5.7的多源复制

    MySQL 5.7已经开始支持了多源复制,相信小伙们都很激动,MySQL 5.7之前只能实现一主一从.一主多从或者多主多从的复制,如果想实现多主一从的复制,只好使用MariaDB,但是MariaDB又 ...

  7. OrCAD Capture CIS 16.6 导出BOM

    OrCAD Capture CIS 16.6 一.选择设计文件:菜单:Tools > Bill of Materials... 二.Bill of Materials > Open in ...

  8. Python中字符串的截取,列表的截取

    字符串的截取 Python中的字符串用单引号 ' 或双引号 " 括起来,同时使用反斜杠 \ 转义特殊字符. 字符串的截取的语法格式如下: 变量[头下标:尾下标] 索引值以 0 为开始值,-1 ...

  9. JS实现继承的几种方式(转)

    转自:幻天芒的博客 前言 JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一.那么如何在JS中实现继承呢?让我们拭目以待. JS继承的实现方式 既然要实现继承,那么首先我们得有一个父类,代码如 ...

  10. JS判断元素 动画是否执行完成

    使用animationend方法 var ele = document.getElementById("box"); ele.addEventListener("anim ...