文档章节

Mybatis分页和Spring的集成

miemiedev
 miemiedev
发布于 2013/06/04 14:25
字数 1001
阅读 48778
收藏 115

写了一个Mybatis分页控件,在这记录一下使用方式。

在Maven中加入依赖:

<dependencies>
  ...
    <dependency>
        <groupId>com.github.miemiedev</groupId>
        <artifactId>mybatis-paginator</artifactId>
        <version>1.2.17</version>
    </dependency>
 ...
</dependencies>


Mybatis配置文件添加分页插件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"
        "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
<configuration>
    <plugins>
        <plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor">
            <property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.OracleDialect"/>
        </plugin>
    </plugins>
</configuration>


创建一个查询,内容可以是任何Mybatis表达式,包括foreach和if等:

<select id="findByCity" resultType="map">
    select * from TEST_USER where city = #{city};
</select>


Dao中的方法或许是这样(用接口也是类似):

public List findByCity(String city, PageBounds pageBounds){

    Map<String, Object> params = new HashMap<String, Object>();
    params.put("city",city);

    return getSqlSession().selectList("db.table.user.findByCity", params, pageBounds);
}


调用方式(分页加多列排序):

int page = 1; //页号
int pageSize = 20; //每页数据条数
String sortString = "age.asc,gender.desc";//如果你想排序的话逗号分隔可以排序多列
PageBounds pageBounds = new PageBounds(page, pageSize , Order.formString(sortString));
List list = findByCity("BeiJing",pageBounds);

//获得结果集条总数
PageList pageList = (PageList)list;
System.out.println("totalCount: " + pageList.getPaginator().getTotalCount());

PageList类是继承于ArrayList的,这样Dao中就不用为了专门分页再多写一个方法。

使用PageBounds这个对象来控制结果的输出,常用的使用方式一般都可以通过构造函数来配置。

new PageBounds();//默认构造函数不提供分页,返回ArrayList
new PageBounds(int limit);//取TOPN操作,返回ArrayList
new PageBounds(Order... order);//只排序不分页,返回ArrayList

new PageBounds(int page, int limit);//默认分页,返回PageList
new PageBounds(int page, int limit, Order... order);//分页加排序,返回PageList
new PageBounds(int page, int limit, List<Order> orders, boolean containsTotalCount);//使用containsTotalCount来决定查不查询totalCount,即返回ArrayList还是PageList


========================================= 

如果用的是Spring MVC的话可以把JSON的配置写成这样:

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.StringHttpMessageConverter"> 
            <constructor-arg value="UTF-8" />        
        </bean>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="com.github.miemiedev.mybatis.paginator.jackson2.PageListJsonMapper" />
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>


那么在Controller就可以这样用了:

@ResponseBody
@RequestMapping(value = "/findByCity.json")
public List findByCity(@RequestParam String city,
                 @RequestParam(required = false,defaultValue = "1") int page,
                 @RequestParam(required = false,defaultValue = "30") int limit,
                 @RequestParam(required = false) String sort,
                 @RequestParam(required = false) String dir) {
    return userService.findByCity(city, new PageBounds(page, limit, Order.create(sort,dir)));
}


然后序列化后的JSON字符串就会变成这样的:

{
    "items":[
        {"NAME":"xiaoma","AGE":30,"GENDER":1,"ID":3,"CITY":"BeiJing"},
        {"NAME":"xiaoli","AGE":30,"SCORE":85,"GENDER":1,"ID":1,"CITY":"BeiJing"},
        {"NAME":"xiaowang","AGE":30,"SCORE":92,"GENDER":0,"ID":2,"CITY":"BeiJing"},
        {"NAME":"xiaoshao","AGE":30,"SCORE":99,"GENDER":0,"ID":4,"CITY":"BeiJing"}
    ],
    "slider": [1, 2, 3, 4, 5, 6, 7],
    "hasPrePage": false,
    "startRow": 1,
    "offset": 0,
    "lastPage": false,
    "prePage": 1,
    "hasNextPage": true,
    "nextPage": 2,
    "endRow": 30,
    "totalCount": 40351,
    "firstPage": true,
    "totalPages": 1346,
    "limit": 30,
    "page": 1
}


=========================================

在SpringMVC中使用JSTL的话可以参考一下步骤(懒人用法)

在Spring配置文件中加入拦截器,或则参考拦截器实现定义自己的拦截器

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**" />
        <bean class="com.github.miemiedev.mybatis.paginator.springmvc.PageListAttrHandlerInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

然后Controller方法可以这样写

@RequestMapping(value = "/userView.action")
public ModelAndView userView(@RequestParam String city,
                 @RequestParam(required = false,defaultValue = "1") int page,
                 @RequestParam(required = false,defaultValue = "30") int limit,
                 @RequestParam(required = false) String sort,
                 @RequestParam(required = false) String dir) {
    List users = userService.findByCity(city, new PageBounds(page, limit, Order.create(sort,dir)));
    return new ModelAndView("account/user","users", users);
}

JSP中就可以这样用了,拦截器会将PageList分拆添加Paginator属性,默认命名规则为"原属性名称"+"Paginator"

<table>
    <c:forEach items="${users}" var="user">
        <tr>
            <td>${user['ID']}</td>
            <td>${user['NAME']}</td>
            <td>${user['AGE']}</td>
        </tr>
    </c:forEach>
</table>
上一页: ${usersPaginator.prePage} 
当前页: ${usersPaginator.page} 
下一页: ${usersPaginator.nextPage} 
总页数: ${usersPaginator.totalPages} 
总条数: ${usersPaginator.totalCount} 
更多属性参考Paginator类提供的方法

=========================================

如果用如下方法设置pageBounds,当前这个查询就可以用两个线程同时查询list和totalCount

pageBounds.setAsyncTotalCount(true);

如果所有的分页查询都是用异步的方式查询list和totalCount,可以在插件配置加入asyncTotalCount属性

<plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor">
    <property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.OracleDialect"/>
    <property name="asyncTotalCount" value="true"/>
</plugin>

但是你仍然可以用下面代码强制让这个查询不用异步

pageBounds.setAsyncTotalCount(false);

当然需要注意的是,只要你用到了异步查询,由于里面使用了线程池,所以在使用时就要加入清理监听器,以便在停止服务时关闭线程池。需要在web.xml中加入

<listener>
    <listener-class>com.github.miemiedev.mybatis.paginator.CleanupMybatisPaginatorListener</listener-class>
</listener>


完。

© 著作权归作者所有

共有 人打赏支持
miemiedev

miemiedev

粉丝 71
博文 2
码字总数 1543
作品 2
济南
程序员
私信 提问
加载中

评论(108)

修改性别
修改性别
HTTP Status 500 - Request processing failed; nested exception is java.lang.ClassCastException: java.util.ArrayList cannot be cast to com.github.miemiedev.mybatis.paginator.domain.PageList
oaoit
oaoit
是物理分页吗?
diaosidiaosi
diaosidiaosi
楼主  能将数据库表给我们看下吗?
z
zxc旭
楼主,为什么我的
(int page = 1; //页号
    int pageSize = 20; //每页数据条数
    String sortString = "StudentNo.asc";//如果你想排序的话逗号分隔可以排序多列
    PageBounds pageBounds = new PageBounds(page, pageSize , Order.formString(sortString),true);
    //PageBounds pageBounds = new PageBounds(page, pageSize,true);
    PageList pageList = studentSvc.findByCity("",pageBounds);
    Paginator paginator = pageList.getPaginator();)
总页数:paginator 始终是Null呢?
huffmans
huffmans
好使79
xingeryue
xingeryue

引用来自“miemiedev”的评论

引用来自“唐文韬”的评论

您好,我在PageList pageList = (PageList)list; 强制转换这里报错了,我有点不解,为啥这里来个强转,就能取到Paginator对象? 我debug了下,list就是一个普通的List对象,如何能变出一个Paginator对象?

区别在于containsTotalCount参数是否为true。有时候只想取TopN就可以不查询记录总数了。
您好, 我在用 List users = testlist(pageForm); PageList pageList = (PageList)users; 时 始终报错,类型转换错误,我也检查了很多次,是不是哪里的配置有问题?
miemiedev
miemiedev

引用来自“mascothaojun”的评论

我发现Mybatis配置文件添加分页插件,加不加都行的?是不是这个原因?因为系统没读取该配置文件,所以就出现这种问题?

引用来自“miemiedev”的评论

你要是debug能到OffsetLimitInterceptor这个类就说明插件正确配置了

引用来自“mascothaojun”的评论

那为什么查找的语句,没有加上rownum的筛选呢?是不是我这个表是同义词的问题?

引用来自“miemiedev”的评论

那个PageBounds就是个Bean,你设置了不太可能还会是2147483647的

引用来自“mascothaojun”的评论

http://blog.163.com/jekyll_zhou@126/blog/static/182047382012103033035925/ 我的问题,和这个是同一个问题,所以你这里可能要改造一下,呵呵!希望我提的建议有用!
谢谢你的建议
m
mascothaojun

引用来自“mascothaojun”的评论

我发现Mybatis配置文件添加分页插件,加不加都行的?是不是这个原因?因为系统没读取该配置文件,所以就出现这种问题?

引用来自“miemiedev”的评论

你要是debug能到OffsetLimitInterceptor这个类就说明插件正确配置了

引用来自“mascothaojun”的评论

那为什么查找的语句,没有加上rownum的筛选呢?是不是我这个表是同义词的问题?

引用来自“miemiedev”的评论

那个PageBounds就是个Bean,你设置了不太可能还会是2147483647的
http://blog.163.com/jekyll_zhou@126/blog/static/182047382012103033035925/ 我的问题,和这个是同一个问题,所以你这里可能要改造一下,呵呵!希望我提的建议有用!
m
mascothaojun

引用来自“mascothaojun”的评论

我发现Mybatis配置文件添加分页插件,加不加都行的?是不是这个原因?因为系统没读取该配置文件,所以就出现这种问题?

引用来自“miemiedev”的评论

你要是debug能到OffsetLimitInterceptor这个类就说明插件正确配置了

引用来自“mascothaojun”的评论

那为什么查找的语句,没有加上rownum的筛选呢?是不是我这个表是同义词的问题?

引用来自“miemiedev”的评论

那个PageBounds就是个Bean,你设置了不太可能还会是2147483647的
原来是dubbo的框架和你写的代码有冲突的问题,因为dubbo是通过反射来查找你当前的 limit的值,但是你的类里面 limit有两个值,构造方法当前的值是已经更改了,但是父类的值没修改,所以反射的时候,可能只拿到父类的值,所以导致rownum没追加成功.
m
mascothaojun

引用来自“mascothaojun”的评论

我发现Mybatis配置文件添加分页插件,加不加都行的?是不是这个原因?因为系统没读取该配置文件,所以就出现这种问题?

引用来自“miemiedev”的评论

你要是debug能到OffsetLimitInterceptor这个类就说明插件正确配置了

引用来自“mascothaojun”的评论

那为什么查找的语句,没有加上rownum的筛选呢?是不是我这个表是同义词的问题?

引用来自“miemiedev”的评论

那个PageBounds就是个Bean,你设置了不太可能还会是2147483647的
您好,经过测试后,原来是dubbo的框架是这样的,因为现在我们的项目是分成三层开发的,web是一个工程,然后api工程只放接口暴露给web工程访问,,最后后台逻辑的工程,但是limit在web访问的时候,就出现问题了,值传不过去,所以就出现没法加rownum的原因!
Mybatis-PageHelper的使用

Mybatis-PageHelper一个简洁易用的mybatis分页插件。 文档地址:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/README_zh.md 加入依赖 使用的时候分两步。 第一步:在mybat...

_流云_
2017/04/18
0
0
新书上架:《Spring Boot 开发实战》基于 Kotlin + Gradle + Spring Boot 2.0 的企业级服务端开发实战

新书上架:《Spring Boot 开发实战》 — 基于 Kotlin + Gradle + Spring Boot 2.0 的企业级服务端开发实战 京东下单链接 https://item.jd.com/31178320122.html 天猫下单链接 https://detail...

程序员诗人
08/22
0
0
itdragons/espread

JAVA后台管理系统 Espread Espread基于Spring、SpringMVC、Mybatis、Shiro、Quartz、Maven、Easyui写的一个后台管理系统,集成Generator Sql生成器、多数据源切换、Aop日志、Mybatis通用Map...

itdragons
2017/11/30
0
0
新书上架:《Spring Boot 开发实战》(基于 Kotlin + Gradle + Spring Boot 2.0 的企业级服务端开发实战)

新书上架:《Spring Boot 开发实战》 — 基于 Kotlin + Gradle + Spring Boot 2.0 的企业级服务端开发实战 京东下单链接 https://item.jd.com/31178320122.html 天猫下单链接 https://detail...

程序员诗人
08/05
0
0
构建dubbo分布式平台-maven构建ant-framework核心代码Base封装

因为涉及到springmvc、mybatis的集成,为了使项目编码更简洁易用,这边将基础的BASE进行封装,其中包括:BaseBean、BaseDao、BaseService、CRUD的基础封装、分页组件的封装、mybatis的mappe...

明理萝
08/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

get和post详解

get和post是表单提交的两种方式,get请求数据通过域名后缀URL传送,用户可见,不安全,post请求数据通过在请求报文正文里传输,相对比较安全。get是通过URL传递表单值,post通过URL看不到表单...

青衣霓裳
昨天
2
0
linux-如何快速替换IP

在Linux在做高可用的时候,经常会使用到虚拟IP。在windows上一个网卡可以配置两个IP,在Linux直接使用ip命令就可以添加了。 添加 ip address add 192.168.1.200/24 broadcast 192.168.1.255 ...

Linux就该这么学
昨天
2
0
Unix-Linux 编程实践教程 第五章 小结

设备文件中用逗号连接起来的两个数字为主设备号和从设备号。主设备号确定实际的设备驱动程序,从设备号作为参数。 如下图中的,主设备号-4,从设备号-2 设备文件中的i-node存储的是指向内核子...

Explorer0
昨天
2
0
Rabbitmq---消息队列

一 . MQ:message queue   消息队列的作用:   1 通信解耦   2 高峰限流 原理分析: 一开始,认证系统是强耦合的,A系统传递认证系统消息接收计算结果的过程中   1 传给认证系统   2 认...

Ala6
昨天
32
0
记一次使用SimpleDateFormat 格式化时间时遇到的问题

网上的使用方法一大堆,我就不再介绍了,就写一下自己遇到的问题. 先来实现一下获取当前时间: SimpleDateFormat simpleDateFormat =new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");String no...

编程SHA
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部