Spring Boot+MyBatis:用 PageHelper 实现 Oracle 12c 的 OFFSET 分页

在分页场景中,不同数据库的分页语法差异很大 ------ 比如 MySQL 用LIMIT,而Oracle 12c 开始支持更灵活的OFFSET ... FETCH语法。今天结合 PageHelper,分享如何在 Spring Boot 中适配 Oracle 12c 的分页方式。

一、PageHelper 基础:引入与自动配置

首先在 Spring Boot 中引入 PageHelper 依赖(以 Maven 为例):

XML 复制代码
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.7</version> <!-- 建议用最新稳定版 -->
</dependency>
<dependency>
    <groupId>com.github.jsqlparser</groupId>
    <artifactId>jsqlparser</artifactId>
    <version>4.6</version> <!-- 适配SQL解析的版本 -->
</dependency>

Spring Boot 会自动配置 PageHelper,无需额外代码~

二、核心:自定义 Oracle 12c 分页方言

PageHelper 默认的 Oracle 方言用的是ROWNUM语法(适配旧版本),而 Oracle 12c 支持更简洁的OFFSET ... FETCH。我们需要自定义方言,重写分页 SQL 生成逻辑

步骤 1:编写 Oracle 12c 方言类

继承AbstractHelperDialect,实现getPageSql方法,拼接OFFSET ... FETCH语法:

java 复制代码
@Component
public class Oracle12cDialect extends AbstractHelperDialect {
    // 注册方言别名,后续配置用
    static {
        PageAutoDialect.registerDialectAlias("oracle12c", Oracle12cDialect.class);
    }

    @Override
    public String getPageSql(String sql, Page page, CacheKey pageKey) {
        StringBuilder sqlBuilder = new StringBuilder(sql.length() + 40);
        sqlBuilder.append(sql);
        // 拼接Oracle 12c的分页语法:OFFSET 跳过行数 FETCH NEXT 取行数 ROWS ONLY
        int offset = page.getStartRow();
        int limit = page.getPageSize();
        sqlBuilder.append(" OFFSET ").append(offset).append(" ROWS FETCH NEXT ").append(limit).append(" ROWS ONLY");
        
        pageKey.update(offset);
        pageKey.update(limit);
        return sqlBuilder.toString();
    }

    @Override
    public Object processPageParameter(MappedStatement ms, Map<String, Object> paramMap, Page page, BoundSql boundSql) {
        // 这里无需额外参数(OFFSET/FETCH直接拼接在SQL中),返回原参数即可
        return paramMap;
    }
}

步骤 2:配置方言

application.properties中指定使用自定义的oracle12c方言:

bash 复制代码
# 指定Oracle 12c方言
pagehelper.helper-dialect=oracle12c
# 分页合理化(pageNum<=0查第1页,pageNum>总页数查最后一页)
pagehelper.reasonable=true
# 支持通过Mapper接口传分页参数
pagehelper.support-methods-arguments=true

三、使用示例:一行代码实现分页

在 Service 层调用PageHelper.startPage,后续 MyBatis 查询会自动拼接 Oracle 12c 的分页 SQL:

java 复制代码
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public Page<User> listUsers(int pageNum, int pageSize) {
        // 1. 开启分页(pageNum:页码;pageSize:每页条数)
        PageHelper.startPage(pageNum, pageSize);
        // 2. 执行查询(自动拼接OFFSET ... FETCH)
        List<User> userList = userMapper.selectAll();
        // 3. 包装为Page对象(包含总条数、分页信息)
        return new PageInfo<>(userList).toPage();
    }
}

四、对比:Oracle 旧版与 12c 分页语法

  • 旧版(ROWNUM) :需要嵌套子查询,语法繁琐

    sql 复制代码
    SELECT * FROM (
        SELECT t.*, ROWNUM rn FROM (SELECT * FROM user) t
        WHERE ROWNUM <= 20
    ) WHERE rn > 10
  • Oracle 12c(OFFSET/FETCH) :简洁直观(PageHelper 通过自定义方言自动生成)

    sql 复制代码
    SELECT * FROM user OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

通过自定义 PageHelper 方言,就能让 MyBatis 完美适配 Oracle 12c 的现代分页语法啦~

完整 Oracle 12c 分页 Demo(SpringBoot+MyBatis+PageHelper)

相关推荐
写了20年代码的老程序员6 小时前
写了 20 年 Java,我受够了 MyBatis 的 4 个瞬间
mybatis·orm
jameslogo6 小时前
如何用RocketMQTemplate发送事务消息
java·spring boot·rocketmq
码上有光7 小时前
MySQL基本查询
数据库·mysql·oracle·期末快速复习
无关86887 小时前
Spring Boot 项目标准化部署打包实战
java·spring boot·后端
jay神8 小时前
基于微信小程序课外创新实践学分认定系统
java·spring boot·小程序·vue·毕业设计
阿丰资源8 小时前
基于Spring Boot的酒店客房管理系统
java·spring boot·后端
zzqssliu9 小时前
SpringBoot框架搭建跨境独立站|Taocarts代购系统订单模块深度开发
java·spring boot·后端
武子康9 小时前
Java-219 RocketMQ Spring Boot 集成指南:生产者与消费者实战
java·spring boot·分布式·kafka·消息队列·rocketmq·java-rocketmq
想学习java初学者10 小时前
SpringBoot整合GS1编码解码
java·spring boot·后端
i220818 Faiz Ul11 小时前
智慧养老平台|基于SprinBoot+vue的智慧养老平台系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·毕设·智慧养老平台