如何在MyBatis中通过Oracle序列实现主键自增的最佳实践是什么

夜辰酱_1123

夜辰酱_1123

2026-07-17

1029人浏览

原创

Oracle不支持主键自增,MyBatis中useGeneratedKeys="true"无效,必须用selectKey标签配合序列NEXTVAL(order="BEFORE")显式获取ID,否则id字段为null;批量插入时selectKey只执行一次,需预生成ID列表或改用触发器/MyBatis-Plus序列生成器。

oracle 本身不支持主键自增,mybatis 中必须显式获取序列值;直接用 usegeneratedkeys="true" 会失效,且无法返回 id —— 这是绝大多数人踩坑的起点。

为什么不能用 useGeneratedKeys

Oracle 没有类似 MySQL 的 `LAST_INSERT_ID()` 或 SQL Server 的 `SCOPE_IDENTITY()` 机制,useGeneratedKeys 依赖数据库原生自增能力,对 Oracle 完全无效。哪怕你在 标签里硬加上 useGeneratedKeys="true" 和 keyProperty="id",执行后 id 字段仍为 null 或 0,不会自动填充。

  • MyBatis 日志里会出现类似 Updates: 1,但无主键回写
  • 若同时配置了 selectKey 和 useGeneratedKeys="true",后者会被忽略,但容易造成逻辑混淆
  • MyBatis Plus 中也需禁用 IdType.AUTO,改用 IdType.INPUT + 序列名

推荐做法:selectKey + 序列 NEXTVAL(BEFORE)

这是最稳定、兼容性最好、无需额外数据库对象的方式,适用于单条插入和大多数批量场景(只要不是真·高并发批量插入)。

  • 在 内部嵌入 ,order="BEFORE" 确保先取值再插入
  • keyProperty 必须与 Java 对象字段名完全一致(如 userId),且类型要匹配(resultType="long" 或 "java.lang.Long")
  • SQL 必须写成 SELECT seq_user.NEXTVAL FROM DUAL,不能漏掉 FROM DUAL,否则 Oracle 报 ORA-00923: FROM keyword not found
  • 示例:
<insert id="insertUser" parametertype="User"><selectkey keyproperty="id" resulttype="long" order="BEFORE">
    SELECT seq_user.NEXTVAL FROM DUAL
  </selectkey>
  INSERT INTO users (id, name) VALUES (#{id}, #{name})
</insert>

批量插入时的序列处理陷阱

MyBatis 的 批量插入中, 只执行一次 —— 这意味着所有记录会拿到同一个序列值,导致唯一约束冲突或数据覆盖。

QuantOracle
QuantOracle

63个确定性量化金融计算器 + 10个通过MCP的复合工作流。期权定价、Greeks、奇异衍生品、风险指标、投资组合优化……

下载
  • 错误写法: 放在 外层,然后用 插入多条,全部共用一个 #{id}
  • 可行方案一:改用数据库端生成(如触发器),但失去应用层对 ID 的控制权
  • 可行方案二:Java 层预生成 ID 列表,调用 seq_user.NEXTVAL N 次(可用 SELECT seq_user.NEXTVAL FROM DUAL CONNECT BY LEVEL 一次性查出 N 个值)
  • 可行方案三:用 MyBatis-Plus 的 OracleKeyGenerator 配合 @KeySequence 注解,它内部会按需多次调用序列

序列创建与缓存注意事项

序列不是“开箱即用”的安全组件,缓存(CACHE)和事务行为直接影响 ID 连续性与可靠性。

  • 默认 CACHE 20 会预分配 20 个值到内存;数据库异常重启会导致跳号(最多丢 20 个)
  • 如果业务要求严格连续(如财务流水号),必须加 NOCACHE,但性能下降明显
  • 避免用 START WITH 0 或负数起始,某些 JDBC 驱动对负 ID 解析异常
  • 序列名建议统一前缀,如 SEQ_USER,避免和表名、触发器名冲突

真正难的不是怎么写那几行 XML,而是想清楚:你的 ID 是否允许跳号?是否需要全局唯一而非单表唯一?是否要支持分布式部署?这些决定了你该用序列、UUID(sys_guid())、还是雪花算法 —— 而 Oracle 序列,只是其中一种确定性高、成本低、但中心化强的选择。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

oracle

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
mybatis一级缓存和二级缓存
mybatis一级缓存和二级缓存

在MyBatis中,一级缓存和二级缓存是两种不同级别的缓存机制,它们都可以用来提高性能。本专题提供mybatis一级缓存和二级缓存相关文章,大家可以免费阅读。

2023.08.21

603

4

ibatis和mybatis有什么区别
ibatis和mybatis有什么区别

ibatis和mybatis的区别:1、基本信息不同;2、开发时间不同;3、功能与易用性;4、配置文件;5、入参类型与出参类型;6、返回结果集接受方式;7、语法差异;8、数据库方言支持;9、插件支持;10、社区活跃度;11、全球化支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

2962

5

mybatis如何配置数据库连接
mybatis如何配置数据库连接

mybatis配置数据库连接的方法:1、指定数据源;2、配置事务管理器;3、配置类型处理器和映射器;4、使用环境元素;5、配置别名。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

446

5

mybatis工作原理及流程是什么
mybatis工作原理及流程是什么

mybatis工作原理及流程:1、配置文件;2、接口与映射;3、sql解析与生成;4、执行计划;5、结果处理;6、动态sql;7、缓存机制;8、插件;9、事务管理;10、日志与监控;11、扩展性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

292

4

hibernate和mybatis有哪些区别
hibernate和mybatis有哪些区别

hibernate和mybatis的区别:1、实现方式;2、性能;3、对象管理的对比;4、缓存机制。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

302

5

Java MyBatis框架
Java MyBatis框架

本专题专注于Java主流ORM框架MyBatis的应用,系统讲解SQL映射、动态SQL、结果映射、分页查询、缓存机制与多表关联等核心内容,并结合企业管理系统、电商平台和后台管理项目实战,帮助学员全面掌握高效的数据库持久层开发技能。

2025.08.26

6369

22

oracle清空表数据
oracle清空表数据

当表中的数据不需要时,则应该删除该数据并释放所占用的空间。本专题为大家提供oracle清空表数据的相关文章,帮助大家解决该问题。

2023.08.16

1121

5

Oracle中declare的使用
Oracle中declare的使用

Oracle DECLARE语句是PL/SQL编程语言中用于声明变量、常量、游标或异常的关键字。它的主要作用是在程序中定义这些对象,以便在后续的代码中使用。DECLARE语句的语法简单明了,可以根据需要声明多个对象。通过使用这些声明的对象,可以进行各种操作,如计算、查询数据库、处理异常等 。

2023.09.15

3293

5

oracle怎么分页
oracle怎么分页

实现分页的步骤:1、使用ROWNUM进行分页查询;2、在执行查询之前进行设置分页参数;3、使用"COUNT(*)"函数来获取总行数,并使用"CEIL"函数来向上取整计算总页数;4、在外部查询中使用"WHERE"子句来筛选出特定的行号范围,以实现分页查询。想了解更多oracle怎么分页的文章,可以来阅读本专题先的文章。

2023.09.18

3290

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程