Quarkus-Hibernate-Envers中REVINFO_SEQ序列未更新问题
使用版本:quarkus-hibernate-envers、quarkus-hibernate-orm-panache、quarkus-liquibase:3.20.0
实体类代码
@Data @Entity @Table(name = "blah") @AuditTable("blah_audit") @Audited public class Blah{ @Id @SequenceGenerator(name = "blah_id_seq", sequenceName = "blah_id_seq", allocationSize = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "blah_id_seq") private Long id; }
Liquibase迁移脚本
<createSequence sequenceName="REVINFO_SEQ"/> <createTable tableName="REVINFO"> <column name="REV" type="int" defaultComputedValue="nextval('REVINFO_SEQ')"> <constraints primaryKey="true"/> </column> <column name="REVTSTMP" type="bigint"/> </createTable> <!-- plus necessary blah and blah_audit tables -->
问题现象
运行应用并持久化新的或已有的Blah对象时,审计记录能成功生成,但执行以下查询后发现异常:
select last_value from revinfo_seq; select rev, revtstmp, to_timestamp(revtstmp/1000) from revinfo;
REVINFO表中的REV值正常递增,但REVINFO_SEQ序列的last_value并未更新。重启应用后,若不手动更新序列,会触发REV重复键冲突。
期望结果
REVINFO_SEQ序列能随审计记录的生成自动更新,避免重启后的重复键问题。
问题根源在于Hibernate Envers默认不会使用手动创建的REVINFO_SEQ序列生成REV值,而是自行维护REV递增逻辑,导致序列与表中值脱节。
方案1:配置Envers使用指定序列生成REV值
在application.properties中添加配置,让Envers明确使用自定义序列:
# 指定Envers的修订号生成策略为序列 quarkus.hibernate-orm.envers.revision-generator.strategy=sequence # 指定使用的序列名称 quarkus.hibernate-orm.envers.revision-generator.sequence-name=REVINFO_SEQ
同时修改Liquibase脚本,移除REV列的defaultComputedValue属性——现在由Envers负责生成REV值,无需数据库默认值:
<createSequence sequenceName="REVINFO_SEQ"/> <createTable tableName="REVINFO"> <column name="REV" type="int"> <constraints primaryKey="true"/> </column> <column name="REVTSTMP" type="bigint"/> </createTable>
方案2:让Envers自动管理REVINFO表和序列(推荐)
如果不需要自定义REVINFO表结构,可直接删除Liquibase中关于REVINFO_SEQ和REVINFO表的创建语句,让Hibernate Envers自动生成对应表和序列。
只需确保application.properties中开启Envers:
quarkus.hibernate-orm.envers.enabled=true
Envers会自动创建符合要求的REVINFO表及对应序列,避免手动配置导致的不一致问题。
临时修复:同步现有序列值
如果已有生产数据,可先执行SQL手动同步序列值到REVINFO表的最大REV值(以PostgreSQL为例):
SELECT setval('REVINFO_SEQ', (SELECT MAX(rev) FROM REVINFO));
内容的提问来源于stack exchange,提问作者netmunky

