PageHelper 代码中的调用!

上一篇文件已经介绍PageHelper 集成 springboot !


分页插件支持以下几种调用方式:

//第一种,RowBounds方式的调用

List<Country> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(0, 10));

//第二种,Mapper接口方式的调用,推荐这种使用方式。

PageHelper.startPage(1, 10);

List<Country> list = countryMapper.selectIf(1);

//第三种,Mapper接口方式的调用,推荐这种使用方式。

PageHelper.offsetPage(1, 10);

List<Country> list = countryMapper.selectIf(1);

//第四种,参数方法调用

//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数

public interface CountryMapper {

? ? List<Country> selectByPageNumSize(

? ? ? ? ? ? @Param("user") User user,

? ? ? ? ? ? @Param("pageNum") int pageNum,

? ? ? ? ? ? @Param("pageSize") int pageSize);

}

//配置supportMethodsArguments=true

//在代码中直接调用:

List<Country> list = countryMapper.selectByPageNumSize(user, 1, 10);

//第五种,参数对象

//如果 pageNum 和 pageSize 存在于 User 对象中,只要参数有值,也会被分页

//有如下 User 对象

public class User {

? ? //其他fields

? ? //下面两个参数名和 params 配置的名字一致

? ? private Integer pageNum;

? ? private Integer pageSize;

}

//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数

public interface CountryMapper {

? ? List<Country> selectByPageNumSize(User user);

}

//当 user 中的 pageNum!= null && pageSize!= null 时,会自动分页

List<Country> list = countryMapper.selectByPageNumSize(user);

//第六种,ISelect 接口方式

//jdk6,7用法,创建接口

Page<Country> page = PageHelper.startPage(1, 10).doSelectPage(new ISelect() {

? ? @Override

? ? public void doSelect() {

? ? ? ? countryMapper.selectGroupBy();

? ? }

});

//jdk8 lambda用法

Page<Country> page = PageHelper.startPage(1, 10).doSelectPage(()-> countryMapper.selectGroupBy());

//也可以直接返回PageInfo,注意doSelectPageInfo方法和doSelectPage

pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(new ISelect() {

? ? @Override

? ? public void doSelect() {

? ? ? ? countryMapper.selectGroupBy();

? ? }

});

//对应的lambda用法

pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(() -> countryMapper.selectGroupBy());

//count查询,返回一个查询语句的count数

long total = PageHelper.count(new ISelect() {

? ? @Override

? ? public void doSelect() {

? ? ? ? countryMapper.selectLike(country);

? ? }

});

//lambda

total = PageHelper.count(()->countryMapper.selectLike(country));

下面对最常用的方式进行详细介绍

1). RowBounds方式的调用

List<Country> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(1, 10));

使用这种调用方式时,你可以使用RowBounds参数进行分页,这种方式侵入性最小,我们可以看到,通过RowBounds方式调用只是使用了这个参数,并没有增加其他任何内容。

分页插件检测到使用了RowBounds参数时,就会对该查询进行物理分页。

关于这种方式的调用,有两个特殊的参数是针对?RowBounds?的,你可以参看上面的?场景一?和?场景二

注:不只有命名空间方式可以用RowBounds,使用接口的时候也可以增加RowBounds参数,例如:

//这种情况下也会进行物理分页查询

List<Country> selectAll(RowBounds rowBounds);?

注意:?由于默认情况下的?RowBounds?无法获取查询总数,分页插件提供了一个继承自?RowBounds?的?PageRowBounds,这个对象中增加了?total?属性,执行分页查询后,可以从该属性得到查询总数。

2).?PageHelper.startPage?静态方法调用

除了?PageHelper.startPage?方法外,还提供了类似用法的?PageHelper.offsetPage?方法。

在你需要进行分页的 MyBatis 查询方法前调用?PageHelper.startPage?静态方法即可,紧跟在这个方法后的第一个MyBatis 查询方法会被进行分页。

例一:

//获取第1页,10条内容,默认查询总数count

PageHelper.startPage(1, 10);

//紧跟着的第一个select方法会被分页

List<Country> list = countryMapper.selectIf(1);

assertEquals(2, list.get(0).getId());

assertEquals(10, list.size());

//分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>

assertEquals(182, ((Page) list).getTotal());

例二:

//request: url?pageNum=1&pageSize=10

//支持 ServletRequest,Map,POJO 对象,需要配合 params 参数

PageHelper.startPage(request);

//紧跟着的第一个select方法会被分页

List<Country> list = countryMapper.selectIf(1);

//后面的不会被分页,除非再次调用PageHelper.startPage

List<Country> list2 = countryMapper.selectIf(null);

//list1

assertEquals(2, list.get(0).getId());

assertEquals(10, list.size());

//分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>,

//或者使用PageInfo类(下面的例子有介绍)

assertEquals(182, ((Page) list).getTotal());

//list2

assertEquals(1, list2.get(0).getId());

assertEquals(182, list2.size());

例三,使用PageInfo的用法:

//获取第1页,10条内容,默认查询总数count

PageHelper.startPage(1, 10);

List<Country> list = countryMapper.selectAll();

//用PageInfo对结果进行包装

PageInfo page = new PageInfo(list);

//测试PageInfo全部属性

//PageInfo包含了非常全面的分页属性

assertEquals(1, page.getPageNum());

assertEquals(10, page.getPageSize());

assertEquals(1, page.getStartRow());

assertEquals(10, page.getEndRow());

assertEquals(183, page.getTotal());

assertEquals(19, page.getPages());

assertEquals(1, page.getFirstPage());

assertEquals(8, page.getLastPage());

assertEquals(true, page.isFirstPage());

assertEquals(false, page.isLastPage());

assertEquals(false, page.isHasPreviousPage());

assertEquals(true, page.isHasNextPage());

3). 使用参数方式

想要使用参数方式,需要配置?supportMethodsArguments?参数为?true,同时要配置?params?参数。 例如下面的配置:

<plugins>

? ? <!-- com.github.pagehelper为PageHelper类所在包名 -->

? ? <plugin interceptor="com.github.pagehelper.PageInterceptor">

? ? ? ? <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->

? ? ? ? <property name="supportMethodsArguments" value="true"/>

? ? ? ? <property name="params" value="pageNum=pageNumKey;pageSize=pageSizeKey;"/>

</plugin>

</plugins>

在 MyBatis 方法中:

List<Country> selectByPageNumSize(

? ? ? ? @Param("user") User user,

? ? ? ? @Param("pageNumKey") int pageNum,

? ? ? ? @Param("pageSizeKey") int pageSize);

当调用这个方法时,由于同时发现了?pageNumKey?和?pageSizeKey?参数,这个方法就会被分页。params 提供的几个参数都可以这样使用。

除了上面这种方式外,如果 User 对象中包含这两个参数值,也可以有下面的方法:

List<Country> selectByPageNumSize(User user);

当从 User 中同时发现了?pageNumKey?和?pageSizeKey?参数,这个方法就会被分页。

注意:pageNum?和?pageSize?两个属性同时存在才会触发分页操作,在这个前提下,其他的分页参数才会生效。

3).?PageHelper?安全调用

1. 使用?RowBounds?和?PageRowBounds?参数方式是极其安全的

2. 使用参数方式是极其安全的

3. 使用 ISelect 接口调用是极其安全的

ISelect 接口方式除了可以保证安全外,还特别实现了将查询转换为单纯的 count 查询方式,这个方法可以将任意的查询方法,变成一个?select 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>();

}

?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,172评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,346评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,788评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,299评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,409评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,467评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,476评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,262评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,699评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,994评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,167评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,499评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,149评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,387评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,028评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,055评论 2 352

推荐阅读更多精彩内容