You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 07:31:12