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)

相关推荐
robinson19882 小时前
Oracle-PG-崖山全表扫描基础算子性能对比
数据库·oracle·全表扫描·崖山·基础算子性能
enjoy编程2 小时前
Spring Boot 4 如何使用Sentinel进行限流?
spring boot·sentinel·限流·熔断降级·流量控制·服务限流·系统负载保护
Jack Sparrow丶2 小时前
Oracle外键查询
数据库·oracle
Hqst_xiangxuajun2 小时前
万兆SFP光纤笼子交换机和PCIE网卡主板上起到什么作用
网络·fpga开发·oracle·sqlite·json·信息与通信
码界奇点3 小时前
基于Spring Boot和Vue.js的房屋出租管理系统设计与实现
vue.js·spring boot·后端·车载系统·毕业设计·源代码管理
幽络源小助理3 小时前
SpringBoot国内旅游景点数据爬虫与可视化分析系统源码 – JavaWeb项目分享
spring boot·后端·爬虫
大叔_爱编程3 小时前
基于人脸识别的互联网课堂考勤系统-springboot
java·spring boot·毕业设计·人脸识别·源码·课程设计·课堂考勤系统
NineData3 小时前
如何通过 NineData 将 Oracle 不停机迁移到 GaussDB
数据库·oracle·gaussdb·数据库管理工具·ninedata·数据库迁移·迁移工具
Leonardo_Fibonacci3 小时前
skbbs-day5
java·开发语言·mybatis