Mybatis-Plus中分页插件PaginationInterceptor的使用

 更新时间:2023年06月21日 15:16:21   作者:互联网全栈开发实战  
我们在开发的过程中,经常会遇到分页操作,本文主要介绍了Mybatis-Plus中分页插件PaginationInterceptor的使用,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧

1. 描述

1.1 MybatisPlusInterceptor

我们在开发的过程中,经常会遇到分页操作,其分为逻辑分页和物理分页,具体可参考我的博文:逻辑分页和物理分页

如果你用的是Mybatis-Plus框架,可用MybatisPlusInterceptor按如下配置分页代码:

/**
 * @author 念兮为美
 * @datetime 2022/11/28 14:10
 * @desc mybatis plus 配置类
 */
@Configuration
public class MybatisPlusConfig {
  @Bean
  public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    // 设置为使用 MYSQL 方言
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return interceptor;
  }
}

如果你用的是低版本spring boot,可用PaginationInterceptor按如下配置:

/**
 * @author 念兮为美
 * @datetime 2022/11/27 15:22
 * @desc mybatis plus 配置类
 */
@Configuration
public class MybatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

MybatisPlusInterceptor插件是核心插件,目前代理了Executor#query、Executor#update、StatementHandler#prepare方法,其属性:

private List<InnerInterceptor> interceptors = new ArrayList<>();

1.2 InnerInterceptor

注意List<InnerInterceptor>泛型中的InnerInterceptormybatis-plus提供的插件都将基于此接口来实现功能,目前已有的功能如下:

  • 自动分页: PaginationInnerInterceptor
  • 多租户:TenantLineInnerInterceptor
  • 动态表名:DynamicTableNameInnerInterceptor
  • 乐观锁:OptimisticLockerInnerInterceptor
  • sql性能规范: IllegalSQLInnerInterceptor
  • 防止全表更新与删除: BlockAttackInnerInterceptor

【注意】使用多个功能需要注意顺序关系,建议使用如下顺序:

  • 多租户
  • 动态表名
  • 分页,乐观锁
  • sql性能规范,防止全表更新与删除

总结:对sql进行单次改造的优先放入,不对sql进行改造的最后放入。

2. 实现

2.1 不带条件的分页查询

编写查询展示类

/**
 * @author 念兮为美
 * @datetime 2023/2/2 09:58
 * @desc 用户查询结果
 */
@NoArgsConstructor
@Data
@ApiModel(description = "用户返回结果")
public class UserPageVo {
  @ApiModelProperty(name = "username", value = "用户名")
  private String username;
  @ApiModelProperty(name = "nickname", value = "昵称")
  private String nickname;
  @ApiModelProperty(name = "userType", value = "用户类型")
  private String userType;
}

编写mapper

@Mapper
public interface UserMapper extends BaseMapper<User> {
   @Select("select " +
            "username,nickname,user_type as userType " +
          "from " +
            "user " +
          "order by " +
            "create_time desc"
  )
  List<UserPageVo> findPageUsers(Page<UserPageVo> page);
}

编写service

@Service
public class UserService extends ServiceImpl<UserMapper, User> {
  @Resource private UserMapper userMapper;
  public Page<UserPageVo> findPageUsers() {
    Long currentPage = 4L;
    Long pageSize = 3L;
    Page<UserPageVo> page = new Page<>(currentPage, pageSize);
    List<UserPageVo> pageUsers = userMapper.findPageUsers(page);
    page.setRecords(pageUsers);
    return page;
  }
}

编写controller

@Api(tags = "用户模块")
@RestController
@RequestMapping("/user")
@Slf4j
@Validated
public class UserController {
  @Autowired private UserService userService;
  @ApiOperationSupport(author = "念兮为美")
  @ApiOperation(value = "用户查询接口")
  @GetMapping("/findPageUsers")
  public Page<UserPageVo> findPageUsers() {
    return userService.findPageUsers();
  }
}

测试运行结果

JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@2ce7d43] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM user
==> Parameters: 
<==    Columns: total
<==        Row: 24
<==      Total: 1
==>  Preparing: select username,nickname,user_type as userType from user order by create_time desc LIMIT ?,?
==> Parameters: 9(Long), 3(Long)
<==    Columns: username, nickname, userType
<==        Row: cs, null, admin
<==        Row: lin, null, admin
<==        Row: test3, null, TEST4
<==      Total: 3

2.2 带条件的分页查询

public class UserService extends ServiceImpl<UserMapper, User> {
  @Resource private UserMapper userMapper;
  public Page<User> findPageUsers() {
    Long currentPage = 1L;
    Long pageSize = 3L;
    Page<User> page = new Page<>(currentPage, pageSize);
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("username", "test5");
    Page<User> userPage = userMapper.selectPage(page, queryWrapper);
    return userPage;
  }

运行结果:

JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@475454ae] will not be managed by Spring
==>  Preparing: SELECT COUNT(*) AS total FROM user WHERE deleted = false AND (username = ?)
==> Parameters: test2(String)
<==    Columns: total
<==        Row: 1
<==      Total: 1
==>  Preparing: SELECT username,nickname,user_type FROM user WHERE deleted=false AND (username = ?) LIMIT ?
==> Parameters: test2(String), 3(Long)
<==    Columns: username, nickname, user_type
<==        Row:  test2, null,TEST6
<==      Total: 1

2.3 简述Page类

简单分页模型, 有如下几个主要属性

/**
 * 查询数据列表
 */
protected List<T> records = Collections.emptyList();
/**
 * 总数
 */
protected long total = 0;
/**
 * 每页显示条数,默认 10
 */
protected long size = 10;
/**
 * 当前页
 */
protected long current = 1;

3. 注意事项

3.1 UncategorizedSQLException异常

在编写mapper.xml中的SQL语句时,或者使用@select注解编写SQL语句时,语句末尾不能使用 ; 结尾,原因是在做分页的时候会在编写的SQL语句后面拼接上limit语句, 导致出现SQL语法错误(UncategorizedSQLException)。

可以参考我的这篇博文:全网最详细的org.springframework.jdbc.UncategorizedSQLException的多种解决方法

3.2 不做记录总数的统计

new Page(queryParam.getCurrent(), queryParam.getSize())的两个参数表示:当前页和每页数量

如果业务需求只需要查询分页做上下页切换而不需要记录总数,可以设置第三个参数false就可以不查询count(),以提高性能,即new Page(queryParam.getCurrent(), queryParam.getSize(), false) ,如下代码所示:

/**
 * @author 念兮为美
 * @datetime 2022/11/28 14:20
 * @desc 用户服务实现类
 */
@Service
public class UserService extends ServiceImpl<UserMapper, User> {
  @Resource private UserMapper userMapper;
  public Page<UserPageVo> findPageUsers() {
    Long currentPage = 4L;
    Long pageSize = 3L;
    Page<UserPageVo> page = new Page<>(currentPage, pageSize, false);
    List<UserPageVo> pageUsers = userMapper.findPageUsers(page);
    page.setRecords(pageUsers);
    return page;
  }

从输出结果看,既没有count操作,如下所示:

JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@466c39de] will not be managed by Spring
==>  Preparing: select username,nickname,user_type as userType from user order by create_time desc LIMIT ?,?
==> Parameters: 9(Long), 3(Long)
<==    Columns: username, nickname, userType
<==        Row: cs, null, admin
<==        Row: lin, null, admin
<==        Row: test3, null, TEST4
<==      Total: 3

到此这篇关于Mybatis-Plus中分页插件PaginationInterceptor的使用的文章就介绍到这了,更多相关Mybatis-Plus PaginationInterceptor 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java判断远程服务器上的文件是否存在的方法

    java判断远程服务器上的文件是否存在的方法

    java判断远程服务器上的文件是否存在的方法,需要的朋友可以参考一下
    2013-03-03
  • Springboot获取前端反馈信息并存入数据库的实现代码

    Springboot获取前端反馈信息并存入数据库的实现代码

    这篇文章主要介绍了Springboot获取前端反馈信息并存入数据库的实现代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java遍历Json的简单实例

    Java遍历Json的简单实例

    这篇文章主要介绍了Java遍历Json的简单实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Spring Boot超大文件上传实现秒传功能

    Spring Boot超大文件上传实现秒传功能

    这篇文章主要介绍了Spring Boot超大文件上传实现秒传功能,在实现分片上传的过程,需要前端和后端配合,比如前后端的上传块号的文件大小,前后端必须得要一致,否则上传就会有问题,需要的朋友可以参考下
    2022-12-12
  • SpringCloud OpenFeign与Ribbon客户端配置详解

    SpringCloud OpenFeign与Ribbon客户端配置详解

    在springcloud中,openfeign是取代了feign作为负载均衡组件的,feign最早是netflix提供的,他是一个轻量级的支持RESTful的http服务调用框架,内置了ribbon,而ribbon可以提供负载均衡机制,因此feign可以作为一个负载均衡的远程服务调用框架使用
    2022-11-11
  • 如何使用ActiveMQ中间件方式发送邮件

    如何使用ActiveMQ中间件方式发送邮件

    这篇文章主要介绍了如何使用ActiveMQ中间件方式发送邮件的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java编程long数据类型的使用问题

    Java编程long数据类型的使用问题

    这篇文章主要介绍了Java编程数据类型long的使用问题,涉及长整型数据的取值范围和不同整数类型的表示方法,需要的朋友可以参考下
    2017-09-09
  • Java8新特性Lambda表达式的一些复杂用法总结

    Java8新特性Lambda表达式的一些复杂用法总结

    lambda表达式是JAVA8中提供的一种新的特性,它支持Java也能进行简单的“函数式编程”。 下面这篇文章主要给大家介绍了关于Java8新特性Lambda表达式的一些复杂用法的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-07-07
  • Java解除文件占用即Dom4j操作后实现xml关流

    Java解除文件占用即Dom4j操作后实现xml关流

    这篇文章主要介绍了Java解除文件占用即Dom4j操作后实现xml关流,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • java并发之原子操作类和非阻塞算法

    java并发之原子操作类和非阻塞算法

    这篇文章主要为大家详细介绍了java并发之原子操作类和非阻塞算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11

最新评论