博客地址http://www.jianshu.com/nb/5226994

引言

对于使用Mybatis时,最头痛的就是写分页,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真不想花双倍的时间写count和select,

如下就是项目在没有使用分页插件的时候的语句

<!-- 根据查询条件获取查询获得的数据量 -->
<select id="size" parameterType="Map" resultType="Long">
select count(*) from help_assist_student
<where>
<if test="stuId != null and stuId != ''">
AND stu_id like
CONCAT(CONCAT('%',
#{stuId,jdbcType=VARCHAR}),'%')
</if>
<if test="name != null and name != ''">
AND name like
CONCAT(CONCAT('%',
#{name,jdbcType=VARCHAR}),'%')
</if>
<if test="deptId != null">
AND dept_id in
<foreach item="item" index="index" collection="deptId" open="("
separator="," close=")">
#{item}
</foreach>
</if>
<if test="bankName != null">
AND bank_name in
<foreach item="item" index="index" collection="bankName"
open="(" separator="," close=")">
#{item}
</foreach>
</if>
</where>
</select>
<!-- 分页查询获取获取信息 -->
<select id="selectByPageAndSelections" parameterType="cn.edu.uestc.smgt.common.QueryBase"
resultMap="BaseResultMap">
select * from help_assist_student
<where>
<if test="parameters.stuId != null and parameters.stuId != ''">
AND stu_id like
CONCAT(CONCAT('%',
#{parameters.stuId,jdbcType=VARCHAR}),'%')
</if>
<if test="parameters.name != null and parameters.name != ''">
AND name like
CONCAT(CONCAT('%',
#{parameters.name,jdbcType=VARCHAR}),'%')
</if>
<if test="parameters.deptId != null">
AND dept_id in
<foreach item="item" index="index" collection="parameters.deptId"
open="(" separator="," close=")">
#{item}
</foreach>
</if>
<if test="parameters.bankName != null">
AND bank_name in
<foreach item="item" index="index" collection="parameters.bankName"
open="(" separator="," close=")">
#{item}
</foreach>
</if>
</where>
order by dept_id,stu_id
limit #{firstRow},#{pageSize}
</select>

可以发现,重复的代码太多,虽然说复制粘贴简单的很,但是文件的长度在成倍的增加,以后翻阅代码的时候头都能大了。

于是希望只写一个select语句,count由插件根据select语句自动完成。找啊找啊,发现PageHelperhttps://github.com/pagehelper/Mybatis-PageHelper 符合要求,于是就简单的写了一个测试项目

1,配置分页插件:

直接从官网上copy的如下:

Config PageHelper

1. Using in mybatis-config.xml

<!--
In the configuration file,
plugins location must meet the requirements as the following order:
properties?, settings?,
typeAliases?, typeHandlers?,
objectFactory?,objectWrapperFactory?,
plugins?,
environments?, databaseIdProvider?, mappers?
-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- config params as the following -->
<property name="param1" value="value1"/>
</plugin>
</plugins>
2. Using in Spring application.xml config org.mybatis.spring.SqlSessionFactoryBean as following: <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- other configuration -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!-- config params as the following -->
<value>
param1=value1
</value>
</property>
</bean>
</array>
</property>
</bean>

我使用第一中方法:

<!-- 配置分页插件 -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
<property name="helperDialect" value="mysql"/>
</plugin>
</plugins>

其余的关于mybatis整合spring的内容就不用提了。

2,编写mapper.xml文件

测试工程就不复杂了,简单的查询一个表,没有条件

<select id="selectByPageAndSelections" resultMap="BaseResultMap">
SELECT *
FROM doc
ORDER BY doc_abstract
</select>

然后在Mapper.java中编写对应的接口

public List<Doc> selectByPageAndSelections();

3,分页

@Service
public class DocServiceImpl implements IDocService {
@Autowired
private DocMapper docMapper; @Override
public PageInfo<Doc> selectDocByPage1(int currentPage, int pageSize) {
PageHelper.startPage(currentPage, pageSize);
List<Doc> docs = docMapper.selectByPageAndSelections();
PageInfo<Doc> pageInfo = new PageInfo<>(docs);
return pageInfo;
}
}

参考文档说明,我使用了PageHelper.startPage(currentPage, pageSize);

我认为这种方式不入侵mapper代码。

其实一开始看到这段代码时候,我觉得应该是内存分页。其实插件对mybatis执行流程进行了增强,添加了limit以及count查询,属于物理分页

再粘贴一下文档说明中的一段话

4. 什么时候会导致不安全的分页?

PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。

只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。

如果代码在进入 Executor 前发生异常,就会导致线程不可用,这属于人为的 Bug(例如接口方法和 XML 中的不匹配,导致找不到 MappedStatement 时), 这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。

但是如果你写出下面这样的代码,就是不安全的用法:

PageHelper.startPage(1, 10);
List<Country> list;
if(param1 != null){
list = countryMapper.selectIf(param1);
} else {
list = new ArrayList<Country>();
}
这种情况下由于 param1 存在 null 的情况,就会导致 PageHelper 生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。 上面这个代码,应该写成下面这个样子: List<Country> list;
if(param1 != null){
PageHelper.startPage(1, 10);
list = countryMapper.selectIf(param1);
} else {
list = new ArrayList<Country>();
}
这种写法就能保证安全。 如果你对此不放心,你可以手动清理 ThreadLocal 存储的分页参数,可以像下面这样使用: List<Country> list;
if(param1 != null){
PageHelper.startPage(1, 10);
try{
list = countryMapper.selectAll();
} finally {
PageHelper.clearPage();
}
} else {
list = new ArrayList<Country>();
}
这么写很不好看,而且没有必要。

4,结果

controller层中简单的调用然后返回json字符串如下:可以看出,结果基于doc_abstract排序后返回1-10条的数据

结语

尽量不要重复造轮子。

mybatis 分页插件的更多相关文章

  1. Mybatis分页插件

    mybatis配置 <!-- mybatis分页插件 --> <bean id="pagehelper" class="com.github.pageh ...

  2. mybatis分页插件以及懒加载

    1.   延迟加载 延迟加载的意义在于,虽然是关联查询,但不是及时将关联的数据查询出来,而且在需要的时候进行查询. 开启延迟加载: <setting name="lazyLoading ...

  3. Mybatis分页插件PageHelper的配置和使用方法

     Mybatis分页插件PageHelper的配置和使用方法 前言 在web开发过程中涉及到表格时,例如dataTable,就会产生分页的需求,通常我们将分页方式分为两种:前端分页和后端分页. 前端分 ...

  4. Mybatis分页插件PageHelper使用

    一. Mybatis分页插件PageHelper使用  1.不使用插件如何分页: 使用mybatis实现: 1)接口: List<Student> selectStudent(Map< ...

  5. SSM 使用 mybatis 分页插件 pagehepler 实现分页

    使用分页插件的原因,简化了sql代码的写法,实现较好的物理分页,比写一段完整的分页sql代码,也能减少了误差性. Mybatis分页插件 demo 项目地址:https://gitee.com/fre ...

  6. Mybatis分页插件——PageHelper

    1.引入依赖 <!-- mybatis分页插件 --> <dependency> <groupId>com.github.pagehelper</groupI ...

  7. Java SSM框架之MyBatis3(三)Mybatis分页插件PageHelper

    引言 对于使用Mybatis时,最头痛的就是写分页,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真不想花双倍的时间写count和select ...

  8. Mybatis学习---Mybatis分页插件 - PageHelper

    1. Mybatis分页插件 - PageHelper说明 如果你也在用Mybatis,建议尝试该分页插件,这个一定是最方便使用的分页插件. 该插件目前支持Oracle,Mysql,MariaDB,S ...

  9. Mybatis分页插件PageHelper的实现

    Mybatis分页插件PageHelper的实现 前言 分页这个概念在做web网站的时候很多都会碰到 说它简单吧 其实也简单 小型的网站,完全可以自己写一个,首先查出数据库总条数,然后按照分页大小分为 ...

  10. 基于Mybatis分页插件PageHelper

    基于Mybatis分页插件PageHelper 1.分页插件使用 1.POM依赖 PageHelper的依赖如下.需要新的版本可以去maven上自行选择 <!-- PageHelper 插件分页 ...

随机推荐

  1. 进入django

    web应用,c/s,b/s架构 c/s: 客户端 服务端 b/s: 浏览器 服务器 HTTP协议: 超文本传输协议 四大特性: 1.基于TCP/IP作用在应用层之上的协议 2.基于请求响应 3.无状态 ...

  2. 爬虫框架 Scrapy

    一 介绍 crapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前Scrapy的用途十分广泛,可用 ...

  3. java学习 之 第一个程序及认识

    以前也看过一系列的java方面的程序,但是还没有正式敲过,今天正式学习并且正式敲出代码.在这里记录下来今日所得 写作工具:Notepad++ 在写作工具方面好多人建议用 记事本,但是我还是认为用 No ...

  4. 【Bootstrap】 typeahead自动补全

    typeahead 这篇文章记录了我在使用typeahead的一些问题,不是很全,但是基本够用. Bootstrap提供typeahead组件来完成自动补全功能. 两种用法: 直接给标签添加属性 &l ...

  5. 一起学爬虫——使用xpath库爬取猫眼电影国内票房榜

    之前分享了一篇使用requests库爬取豆瓣电影250的文章,今天继续分享使用xpath爬取猫眼电影热播口碑榜 XPATH语法 XPATH(XML Path Language)是一门用于从XML文件中 ...

  6. FLASK 的Session和MoudelForm插件

    falsk是小而精的框架,但是热度高, 所有很多爱好者提供了很多扩展插件 功能强大,美而不足的就是兼容稳定性有时候不太好,不过大部分还是很可以的 Flask-Session flask内置sessio ...

  7. 我的 FPGA 学习历程(04)—— 练习 verilog 硬件描述语言

    这篇讲的是使用 verilog 硬件描述语言编写一个 3 - 8 译码器. 3 - 8 译码器是一个简单的组合逻辑,用于实现并转串,其输入输出关系如下: | 输入  |  输出  | -------- ...

  8. Showstopper [POJ3484] [二分] [思维]

    Description 给你n个数列,问哪一个数字在所有的数列中出现了奇数次(最多一个). Sample Input 1 10 1 2 10 1 1 10 1 1 10 1 1 10 1 4 4 1 ...

  9. IDEA_Springboot启动Tomcat报错_APR

    使用idea新建一个Springboot项目 环境:idea+jdk8 启动异常如下: An older version [1.2.14] of the APR based Apache Tomcat ...

  10. 关于finally代码块是否一定被执行的问题

    一般来说,只要执行了try语句,finally就会执行 但是,有以下几种情况需要特殊考虑 具体例子看链接  点击这里 第一点 try代码块没有被执行,意思就是错误在try代码块之前就发生了. 第二点 ...