文档章节

Mybatis分页和Spring的集成

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

引用来自“撕花焚玉”的评论

两个会重复吗
<mvc:annotation -driven /> <mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
.......................
</mvc:annotation-driven>
这个转换器就是在annotation-driven配置的,你得保证当前用的这个annotation-driven是包含转换器的就行。默认只写是不包含转换器的。
撕花焚玉
撕花焚玉
两个会重复吗
<mvc:annotation -driven /> <mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
.......................
</mvc:annotation-driven>
撕花焚玉
撕花焚玉

引用来自“撕花焚玉”的评论

果然 !! 只要配置 <mvc:annotation-driven /> 就不行 返回序列化字符串就不行 ,楼主你知道为什么吗??

引用来自“miemiedev”的评论

能说的更详细点吗
我返回json数据,正常的是[{"id":106,"username":"6","age":6,"password":"6"},{"id":107,"username":"6","age":6,"password":"6"}] 这样的数据,但是现在我想序列化他,返回序列化后的json,根据楼主的配置,页面一直返回的还是没序列之前的,我看去年一个人回复 把 去掉就好了,,,我就尝试的去掉了,果然好了 返回的是序列化后的数据了,我还没搞清楚原因。。。。
miemiedev
miemiedev

引用来自“撕花焚玉”的评论

果然 !! 只要配置 <mvc:annotation-driven /> 就不行 返回序列化字符串就不行 ,楼主你知道为什么吗??
能说的更详细点吗
撕花焚玉
撕花焚玉
果然 !! 只要配置 <mvc:annotation-driven /> 就不行 返回序列化字符串就不行 ,楼主你知道为什么吗??
尹逸韶
尹逸韶

引用来自“尹逸韶”的评论

你好,用你的插件返回的对象都是ArrayList。并且排序不生效,如下:
调用:
String sortString = "status.asc";
PageBounds pageBounds = new PageBounds(index, limit, Order.formString(sortString));
List list = userinfoDao.findPageByCondition(parameters, pageBounds);
return (PageList<FwapUserinfo>) list; //报错java.lang.ClassCastException,调试发现对象为ArrayList

DAO层:
List<T> findPageByCondition(Map<String, Object> parameters, PageBounds rb);
<select id="findPageByCondition" parameterType="map" resultMap="fwapUserinfoRM">
    select <include refid="userinfo_columns"/>
    from FWAP_USERINFO
    <where>
      1=1
      <if test="userAccount != null">
        and USER_ACCOUNT like '%${userAccount}%'
      </if>
      <if test="orgnumber != null">
        and ORGNUMBER=#{orgnumber}
      </if>
      <if test="workdate != null">
        and WORKDATE=#{workdate}
      </if>
      <if test="updatetime != null">
        and UPDATETIME=#{updatetime}
      </if>
    </where>
  </select>

调试发现没有进入到OffsetLimitInterceptor拦截器
尹逸韶
尹逸韶

引用来自“尹逸韶”的评论

你好,用你的插件返回的对象都是ArrayList。并且排序不生效,如下:
调用:
String sortString = "status.asc";
PageBounds pageBounds = new PageBounds(index, limit, Order.formString(sortString));
List list = userinfoDao.findPageByCondition(parameters, pageBounds);
return (PageList<FwapUserinfo>) list; //报错java.lang.ClassCastException,调试发现对象为ArrayList

DAO层:
List<T> findPageByCondition(Map<String, Object> parameters, PageBounds rb);
<select id="findPageByCondition" parameterType="map" resultMap="fwapUserinfoRM">
    select <include refid="userinfo_columns"/>
    from FWAP_USERINFO
    <where>
      1=1
      <if test="userAccount != null">
        and USER_ACCOUNT like '%${userAccount}%'
      </if>
      <if test="orgnumber != null">
        and ORGNUMBER=#{orgnumber}
      </if>
      <if test="workdate != null">
        and WORKDATE=#{workdate}
      </if>
      <if test="updatetime != null">
        and UPDATETIME=#{updatetime}
      </if>
    </where>
  </select>

DAO层用MyBatisRepository注释@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MyBatisRepository { }
尹逸韶
尹逸韶
你好,用你的插件返回的对象都是ArrayList。并且排序不生效,如下:
调用:
String sortString = "status.asc";
PageBounds pageBounds = new PageBounds(index, limit, Order.formString(sortString));
List list = userinfoDao.findPageByCondition(parameters, pageBounds);
return (PageList<FwapUserinfo>) list; //报错java.lang.ClassCastException,调试发现对象为ArrayList

DAO层:
List<T> findPageByCondition(Map<String, Object> parameters, PageBounds rb);
<select id="findPageByCondition" parameterType="map" resultMap="fwapUserinfoRM">
    select <include refid="userinfo_columns"/>
    from FWAP_USERINFO
    <where>
      1=1
      <if test="userAccount != null">
        and USER_ACCOUNT like '%${userAccount}%'
      </if>
      <if test="orgnumber != null">
        and ORGNUMBER=#{orgnumber}
      </if>
      <if test="workdate != null">
        and WORKDATE=#{workdate}
      </if>
      <if test="updatetime != null">
        and UPDATETIME=#{updatetime}
      </if>
    </where>
  </select>
涵冰
涵冰

引用来自“涵冰”的评论

用了分页插件,现在发现有个问题解决不了, 列表中如果新增或删除数据刷新查询的时候, 列表中的数据条数是对的, 但分页总数没变化, 导致页码生成有误, 要等一会再来操作或F5连续刷新多次分页总数才会正确,请帮忙解答一下,十分感谢!

引用来自“miemiedev”的评论

有没有刷新cache?
是指mybatis的缓存吗? 我看了你的分页总数查询, 是有判断缓存, 我将usecache是设置false了, 每次都有执行SQLHelp.getCount, 列表的数据会有变化的, 就是总页数不会变
Spring-generator 1.0.0 版正式发布,Spring 代码生成器

Spring-generator是基于javafx8开发的图形界面Spring代码生成器,使用 Apache FreeMarker作为代码文件的模板,用户可以一键将数据库中的表生成为任意风格的.java代码文件(比如经典的三层模型)...

Mirren
06/19
0
0
SpringBoot | 第九章:Mybatis-plus的集成和使用

前言 本章节开始介绍方面的相关知识点。对于后端开发者而言,和数据库打交道是每天都在进行的,所以一个好用的是很有必要的。目前,绝大部分公司都选择框架作为底层数据库持久化框架。 多说几...

oKong
07/21
0
2
Mybatis 分页插件 PageHelper Starter 1.1.0 发布

Mybatis 分页插件 PageHelper Starter v1.1.0 更新内容: 解决可能会注册两次分页插件的问题(由于属性注解导致的两次加载)。 增加 PageHelperProperties 注入,常用属性可以通过 IDE 自动提...

Liuzh_533
2017/02/05
1K
4
JAVAEE——ssm综合练习:CRM系统(包含ssm整合)

1 CRM项目外观 1. 开发环境 IDE: Eclipse Mars2 Jdk: 1.7 数据库: MySQL 2. 创建数据库 数据库sql文件位置如下图: 创建crm数据库,执行sql 效果如下图: 3. 工程搭建 使用的Bootstrap前端框...

kent鹏
07/11
0
0
基于 JavaFX8 的图形界面 Spring 代码生成器 - Spring-generator

Spring-generator 是基于 javafx8 开发的图形界面 Spring 代码生成器,使用 Apache FreeMarker 作为代码文件的模板,用户可以一键将数据库中的表生成为任意风格的 .java 代码文件(比如经典的...

Mirren
06/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

H264 各种profile

H264规定了三种主要档次,每个档次支持一组特定的编码功能,并支持一类特定的应用。 1、基本档次(Baseline Profile):利用I片和P片支持帧内和帧间编码,支持利用基于上下文的自适应的变长编...

yizhichao
今天
2
0
opencv舌头监测模型+keras神经网络(LeNet)

基于前面使用opencv实现舌头模型检测后,本次主要针对模型参数调优,提高图片识别率。 之前的模型精准率很高,但召回率不一定为1,有时候舌头图片并没有被圈出。所以我们需要调整参数让模型吧...

Sheav
今天
1
0
java虚拟机之类加载机制

注:文中所说的 Class 文件并不是特指存在于具体磁盘中的文件,而是一串二进制字节流,无论是以何种形式存在的都可以。 1. 引言 java 类被虚拟机编译之后成为一个 Class 的字节码文件,该字节...

firepation
今天
1
0
Notpad++ 必备插件

Compare:文件对比 Converter:文件编码转换 FingerText:代码模板 HEX-Editor:十六进制编辑 JSLint:js语法检查 MIMETools:URL加密 JSON Viewer:Json 格式化显示 Light Explorer: 文件目...

SimonAt
今天
3
0
xmind8 破解激活教程

亲测可用! 这里以windows为例来演示,其它操作系统需根据情况修改相应步骤。 下载安装包 首先去xmind国外官网下载对应操作系统的安装包,国内官网的那个是有残缺的,不支持破解。 https://...

冯莉莉莉莉
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部