Mybatis分页插件pageHelper的使用
  • 2024-01-10 18:32:41
  • 2063 热度
  • 0 评论

pageHelper就是mybatis拦截器的一个应用,实现分页查询,支持常见的 12 种数据库的物理分页并支持多种分页方式。

该插件目前支持以下数据库的物理分页:

Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL,DB2,SqlServer(2005,2008),Informix,H2,SqlServer2012,Derby,Phoenix,达梦数据库(dm),阿里云PPAS数据库,神通数据库,HerdDB


如果是springboot, 则可以直接引入pagehelper-spring-boot-starter, 它会帮我们省去许多不必要的配置。

<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.12</version>
</dependency>

SpringBoot配置文件application.properties中配置

pagehelper.helper-dialect=mysql


如果是普通的springmvc类的项目,则引入pageHelper即可。

<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper</artifactId>
  <version>5.1.10</version>
</dependency>

mybatis配置文件SqlMapConfig.xml中配置

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
      <!-- 该参数默认为false -->
      <!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 -->
      <!-- 和startPage中的pageNum效果一样-->
      <property name="offsetAsPageNum" value="true"/>
      <!-- 该参数默认为false -->
      <!-- 设置为true时,使用RowBounds分页会进行count查询 -->
      <property name="rowBoundsWithCount" value="true"/>
      <!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 -->
      <!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)-->
      <property name="pageSizeZero" value="true"/>
      <!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 -->
      <!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
      <!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
      <property name="reasonable" value="true"/>
      <!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 -->
      <!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 -->
      <!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,orderBy,不配置映射的用默认值 -->
      <!-- 不理解该含义的前提下,不要随便复制该配置 -->
      <property name="params" value="pageNum=start;pageSize=limit;"/>
      <!-- 支持通过Mapper接口参数来传递分页参数 -->
      <property name="supportMethodsArguments" value="true"/>
      <!-- always总是返回PageInfo类型,check检查返回类型是否为PageInfo,none返回Page -->
      <property name="returnPageInfo" value="check"/>
    </plugin>
  </plugins>
</configuration>

spring中配置

<!--配置SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:mybatis-config.xml" />
<property name="typeAliasesPackage" value="com.aoChine.model.entity" />
<property name="mapperLocations" value="classpath:mapper/*.xml" />
<!-- 配置mybatis分页插件PageHelper -->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<value>dialect=mysql</value>
</property>
</bean>
</array>
</property> 
</bean>


编写分页代码Mapper这里不编写XML直接使用注解,UserDao类:

@Select("SELECT * FROM t_user")
ArrayList<Map<String,Object>> getUsersAnn();


正常情况下是Controller调用Service,然后让Service调用Dao,这里不写那么麻烦了,PagerController类:

/**
 * http://localhost:8080/plistAnn
 */
@RequestMapping("/plistAnn")
public String plistAnn(Model model){
    PageHelper.startPage(1, 3);
    PageHelper.orderBy("user_id");
    ArrayList<Map<String,Object>> all = userDao.getUsersAnn();
    log.info(JSON.toJSONString(all));
    long count = new PageInfo<Map<String, Object>>(all).getTotal();
    log.info("总条数:" + count);
   return "userList";
}

因为这里是使用SpringBoot做的,启动后直接访问/plistAnn接口即可。

PageHelper.startPage(1, 3);就是为查询分页,PageHelper.orderBy("user_id");是排序,下面是为查询统计一共有多少条数据。

即使用时, 只需提前声明要分页的信息, 得到的结果就是有分页信息的了。如果不想进行count, 只要查分页数据, 则调用: PageHelper.startPage(pageNum, pageSize, false); 即可,避免了不必要的count消耗。


分页不安全的情况

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

只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 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存储的分页参数:

PageHelper.clearPage();


pagehelper.jpg

END



alay

Flame

Hello world!

0 评论
留下评论