Spring Boot集成Hibernate Envers插入数据报负修订号错误排查
Hibernate Envers报「不允许负修订号」排查与修复方案
Negative revision numbers are not allowed 报错的核心触发逻辑是Envers生成审计修订记录时,拿到的修订号小于0。你清空所有审计表、revinfo表后问题仍存在,基本可以排除表内存量脏数据的影响,优先按以下顺序排查:
1. 先排除自定义修订号生成逻辑问题
如果项目自定义实现了RevisionListener接口接管修订号生成逻辑,先做排查:
- 检查监听器内修订号生成代码,是否存在硬编码返回负数、数值类型溢出、计数逻辑错误的问题
- 确认自定义逻辑没有和默认序列生成规则冲突,没有覆盖Envers默认的正整数自增逻辑
如果没有自定义修订监听器,直接进入下一个排查项,90%以上的同类问题都是序列配置异常导致。
2. 定位Oracle侧修订号生成序列的异常
Envers默认依赖Oracle序列生成自增修订号,你导入开发环境dump时大概率把序列对象也同步到了QA环境,但序列的当前值、属性配置没有和清空后的表结构匹配,甚至跨库导入导致序列值溢出为负:
- 第一步先找到revinfo表rev字段关联的序列:未自定义的默认序列名一般为
HIBERNATE_SEQUENCE,如果是revinfo表专属序列,命名一般为REVINFO_REV_SEQ格式,也可以直接查字段默认值确认绑定的序列名 - 执行SQL检查序列配置:
-- 替换为你实际查到的序列名 SELECT sequence_name, min_value, max_value, increment_by, last_number FROM all_sequences WHERE sequence_name = '替换为实际序列名';
- 手动执行序列取值命令验证返回值:
SELECT 替换为实际序列名.NEXTVAL FROM dual;
如果返回值小于0,或者取值远大于/小于revinfo表现有最大rev值,就可以确认是序列异常导致的报错。
注意:多数人清表时只会执行DELETE/TRUNCATE删除表内数据,不会同步重置关联序列的当前值;如果导入的dump里序列增量被误设为-1、或者last_number跨库导入时溢出为负数,就算revinfo表是空的,Envers拿到的修订号依然是负数。
3. 对应修复操作
根据排查到的问题选对应方案修复:
- 序列值异常/不匹配:直接重置序列到正确起始值
-- 先查revinfo表现有最大rev值,空表场景下该值取0 SELECT MAX(rev) FROM revinfo; -- 临时修改序列增量,把序列值推进到正确的起始位置 -- 差值计算规则:预期下一个rev值(max(rev)+1) - 序列当前last_number ALTER SEQUENCE 替换为实际序列名 INCREMENT BY 计算得到的差值; SELECT 替换为实际序列名.NEXTVAL FROM dual; -- 把序列增量改回正常的1 ALTER SEQUENCE 替换为实际序列名 INCREMENT BY 1; -- 验证修复结果,此时返回值应该等于max(rev)+1 SELECT 替换为实际序列名.NEXTVAL FROM dual;
- 如果rev字段用的是Oracle 12c+的identity自增列:清表时没有重置自增起始值的话,执行以下命令重置
TRUNCATE TABLE revinfo REUSE STORAGE IDENTITY (1,1);
- 自定义RevisionListener逻辑问题:修正监听器内的ID生成逻辑,确保返回的修订号为从1开始递增的正整数,避免线程安全问题、数值溢出问题。
修复验证
重启应用后触发数据写入操作,确认:
- 业务数据插入正常,不再抛出负修订号相关报错
- revinfo表新生成的rev值为正整数,且和各审计表内关联的rev字段值匹配
- 连续写入多笔数据时,rev值连续递增,无跳变、负数问题
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

