文档章节

Mybatis分页和Spring的集成

miemiedev
 miemiedev
发布于 2013/06/04 14:25
字数 1001
阅读 48772
收藏 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)

miemiedev
miemiedev

引用来自“二代”的评论

楼主你好,用了一段时间这个"mybatis-paginator"之后,发现或许存在性能问题,用例如下:
已知:table1 中有200万条数据,我要查询前500条。
整理出简单sql语句如下
select * from table1 limit 0,500
执行效率还可以,0.032秒
于是用mybatis-paginator实现,数据访问层使用的sql如下
select * from table1
使用java代码如你所写差不多:
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);
打出日志
Preparing: select * from (select * from table1) tmp_order order by id ASC limit ?
我将该日志放入sql查询分析器查询,居然耗时10秒,继续执行平均值在10秒左右。
由此,目前该框架在mysql的环境下,直接包裹住代码,在外层做limit 的性能实在是不佳,不知道楼主有没有考虑过相关问题?
这个分页只适合一般的情况,数据太多就针对的来做优化吧
Jtoms
Jtoms
新版本中在RPC框架(如:dubbo)PageBounds序列化与反序列化失败,PageList<E>也是一样的问题。
二代
二代
楼主你好,用了一段时间这个"mybatis-paginator"之后,发现或许存在性能问题,用例如下:
已知:table1 中有200万条数据,我要查询前500条。
整理出简单sql语句如下
select * from table1 limit 0,500
执行效率还可以,0.032秒
于是用mybatis-paginator实现,数据访问层使用的sql如下
select * from table1
使用java代码如你所写差不多:
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);
打出日志
Preparing: select * from (select * from table1) tmp_order order by id ASC limit ?
我将该日志放入sql查询分析器查询,居然耗时10秒,继续执行平均值在10秒左右。
由此,目前该框架在mysql的环境下,直接包裹住代码,在外层做limit 的性能实在是不佳,不知道楼主有没有考虑过相关问题?
L_Lawliet
L_Lawliet
哦是跟pojo类无法传入的问题~~~快发布解决版本哦
L_Lawliet
L_Lawliet
PageList pageList = (PageList)list; 转换的时候会报错,arraylist无法转是什么原因呢
diaosidiaosi
diaosidiaosi
usersPaginator.prePage 就是这几个参数都没有渠道值,参考了你的懒人用法, 只使用了jstl的标签库
diaosidiaosi
diaosidiaosi
楼主能给个qq交流下问题吗?
diaosidiaosi
diaosidiaosi
为什么我出现了这个效果,就是页面参数没有穿进去,忘大神指教下
y
yahoo12345
### The error occurred while setting parameters
### SQL: select * from a where a.STATUS IN <foreach collection="couponStatusSet" item="item" index="index" open="(" close=")" separator=","> ? </foreach> limit ?
### Cause: java.lang.reflect.UndeclaredThrowableException

出现了 参数赋值的错误,请帮忙指导,谢谢
y
yt0923666
getSqlSession().selectList("db.table.user.findByCity", params, pageBounds);
这句代码中的"db.table.user.findByCity"是啥参数?!
深入浅出MyBatis-快速入门

深入浅出MyBatis-快速入门 深入浅出MyBatis-Configuration 深入浅出MyBatis-MapperBuilder 深入浅出MyBatis-Sqlsession 深入浅出Mybatis-插件原理 深入浅出Mybatis-分页 深入浅出Mybatis-sql...

perfectspr
2014/11/26
0
1
mybatis-plus 3.0-alpha 发布,代号:超级棒棒糖

mybatis-plus 3.0-alpha 发布,代号:超级棒棒糖 Mybatis-Plus 是一款 Mybatis 动态 SQL 自动注入 Mybatis 增删改查 CRUD 操作中间件, 减少你的开发周期优化动态维护 XML 实体字段,无入侵全...

青苗
07/02
0
0
Archx/spring-agg

#SPRING-AGG 这个一个框架整合案列,包含 SpringMVC/MyBatis/Apache Shiro 。 演示数据 演示数据请导入 db.sql 演示账号密码均为 SpringMVC 配置 演示项目使用的是 RESTful 风格,不是传统的...

Archx
2015/01/12
0
0
# Mybatis分页插件-PageHepler的使用

Mybatis分页插件-PageHepler的使用 使用方法 1. 引入分页插件 引入分页插件一共有下面2种方式,推荐使用Maven方式,这种方式方便更新。 1). 引入Jar包 如果你想使用本项目的jar包而不是直接引...

潘天涯
06/15
0
0
Mybatis通用Mapper

极其方便的使用Mybatis单表的增删改查 项目地址: http://git.oschina.net/free/Mapper 优点? 不客气的说,使用这个通用Mapper甚至能改变你对Mybatis单表基础操作不方便的想法,使用它你能简单的...

java梦想家01
2015/08/03
0
2

没有更多内容

加载失败,请刷新页面

加载更多

SpringBoot本地发布镜像到docker服务器

Eclipse中开发SpringBoot持续集成docker Docker环境 操作系统 [sho-gxj@DockerHost0 ~]$ cat /etc/issueUbuntu 16.04 LTS \n \l docker安装 参考** docker官网 ** docker配置 [sho-gxj@Doc......

o00o
19分钟前
1
0
hadoop需要哪些技术支持

hadoop是一个开源软件框架,可安装在一个商用机器集群中,使机器可彼此通信并协同工作,以高度分布式的方式共同存储和处理大量数据。最初,Hadoop 包含以下两个主要组件:Hadoop Distribute...

本宫没空2
30分钟前
0
0
从姜饼短视频看爱奇艺短视频布局

上个月底,爱奇艺发布了一款按话题维度将短视频进行归类的产品——姜饼短视频App。除了姜饼短视频之外,爱奇艺在今年3月份和6月份分别上线“吃鲸短视频”和“爱奇艺锦视”。与爱奇艺以往的短...

ThinkSNS账号
34分钟前
2
0
mycat入门—配置

mycat主要配置文件有3个,他们各司其职 1、server.xml配置 server.xml配置文件主要作用是: 配置系统相关参数 配置用户访问权限 配置SQL防火墙及SQL拦截功能 server.xml中分为两个节点,一个...

haoyuehong
39分钟前
2
0
客户端 防止订单重复提交 接口处理

如果是浏览器,可以采用session的方法 具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的F...

大灰狼wow
44分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部