OracleKeyGenerator 不会自动推导序列名,必须显式配置@KeySequence(value="SEQ_表名")或使用触发器+IdType.NONE;否则插入ID为null导致ORA-01400。
MyBatis-Plus 的 OracleKeyGenerator 不会自动推导序列名
它根本不会去查数据库元信息(比如 user_sequences),也不解析表名拼接 seq_表名 这类约定。所谓“自动识别”,其实是误传——oraclekeygenerator 是一个空壳实现,只负责调用 nextval,但序列名必须显式提供。
常见错误现象:ORA-02289: sequence does not exist,或插入后 ID 为 null;根本原因就是没配序列名,它默认用空字符串去查,自然找不到。
-
@KeySequence注解的value属性必须写对,例如@KeySequence(value = "SEQ_USER") - 若用全局配置(
mybatis-plus.global-config.key-generator),该生成器本身不持有任何序列名,仍需在每个@TableId(type = IdType.INPUT)实体字段上配合@KeySequence - 不要依赖“命名规范自动匹配”——MyBatis-Plus 没这逻辑,连日志都不会打出来提醒你缺序列名
@TableId(type = IdType.INPUT) 必须搭配手动赋值或 @KeySequence
选 IdType.INPUT 意味着“主键由用户控制”,框架完全不干预生成逻辑。如果你只加了注解却不指定序列、也不在代码里 select SEQ_X.nextval from dual 赋值,那插入时 ID 就是 Java 默认的 null 或 0,直接触发 ORA-01400。
- 正确姿势一:实体字段上同时加
@TableId(type = IdType.INPUT)和@KeySequence(value = "SEQ_ORDER") - 正确姿势二:去掉
@KeySequence,但在 Service 层自己查序列:baseMapper.selectOne(new QueryWrapper().select("SEQ_ORDER.NEXTVAL").last("FROM DUAL")),再塞进对象 - 错误姿势:只写
@TableId(type = IdType.INPUT),以为框架会“智能补全”——它不会,也不会报错,只会静默插 null
配置 OracleKeyGenerator bean 后仍不生效的典型原因
即使你在配置类里声明了 @Bean public OracleKeyGenerator oracleKeyGenerator(),它也只在你显式启用时才起作用。MyBatis-Plus 的全局 ID 生成器默认是空的,不会自动绑定到所有 INSERT 操作。
- 必须配合
@TableId(type = IdType.INPUT)使用,IdType.AUTO或IdType.ASSIGN_ID完全无视这个 bean - Spring Boot 自动配置下,
MybatisPlusAutoConfiguration不会自动注册OracleKeyGenerator,必须手写@Configuration类并确保被扫描到 - 如果项目里存在自定义的
SqlSessionFactoryBean,记得调用setConfiguration(...),否则全局配置(含 key-generator)会被丢弃
替代方案:用触发器 + IdType.NONE 最省事
如果你已在 Oracle 表上建好序列和触发器(如 BEFORE INSERT ON t_user FOR EACH ROW BEGIN SELECT seq_user.NEXTVAL INTO :NEW.id FROM DUAL; END;),那最稳的方式反而是关闭 MyBatis-Plus 的 ID 干预。
- 实体字段用
@TableId(type = IdType.NONE),不加@KeySequence - 全局配置设为
mybatis-plus.global-config.db-config.id-type=none,避免和局部注解冲突 - 插入时完全不设
id字段,让触发器接管——此时连jdbc-type-for-null都不用配,彻底绕过 NULL 绑定问题
这个路径看似“退回到原始方式”,但恰恰避开了 MyBatis-Plus 对 Oracle 序列支持的全部断点:不依赖注解解析、不依赖 bean 注册时机、不依赖版本兼容性。只要触发器存在且语法正确,就一定生效。











