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

使用UUID作为Varchar主键时Hibernate Envers无法持久化审计数据

Spring Boot + Hibernate Envers 下 UUID 主键配置问题解决

问题背景

使用Spring Boot 2.7.2、Hibernate 5.6.9.Final搭配MariaDB,实体主键定义为Varchar(255)类型存储UUID。启用Hibernate Envers后出现兼容性问题,Envers默认要求数值型ID或特殊配置才能支持UUID主键。尝试修改ID类型(String/UUID)、调整@GeneratedValue参数均未解决,出现两类典型报错:

报错1:保留@Type(type="uuid-char")时的异常

org.springframework.orm.jpa.JpaSystemException: The database returned no natively generated identity value; nested exception is org.hibernate.HibernateException: The database returned no natively generated identity value
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:331)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566)
    ...
Caused by: org.hibernate.HibernateException: The database returned no natively generated identity value
    at org.hibernate.id.IdentifierGeneratorHelper.getGeneratedIdentity(IdentifierGeneratorHelper.java:75)
    ...
    at org.hibernate.envers.internal.revisioninfo.DefaultRevisionInfoGenerator.saveRevisionData(DefaultRevisionInfoGenerator.java:67)

报错2:移除@Type(type="uuid-char")时的异常

org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:259)
    ...
Caused by: java.sql.SQLSyntaxErrorException: (conn=145) Incorrect string value: '\x97\x90@9\xA5d...' for column `erpm_db`.`number_directory_entry`.`id` at row 1
    at org.mariadb.jdbc.export.ExceptionFactory.createException(ExceptionFactory.java:280)
    ...

最优解决方案

问题根源在于Envers默认使用的DefaultRevisionEntity采用数据库自增ID(IDENTITY策略),与当前UUID主键的配置冲突,导致保存修订信息时无法获取自增值。以下是无需升级依赖或修改现有主键类型的最优解决方法:

方案1:自定义Envers修订实体

  1. 创建自定义修订实体类
@Entity
@Table(name = "REVINFO")
@RevisionEntity
@Getter
@Setter
public class CustomRevisionEntity {
    @Id
    @GeneratedValue(generator = "uuid")
    @Type(type = "uuid-char")
    @GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
    @Column(name = "REV", length = 36, nullable = false)
    private UUID id;

    @Column(name = "REVTSTMP", nullable = false)
    private Long timestamp;
}
  1. 在Spring Boot配置中指定Envers使用该自定义实体
    在application.properties中添加配置:
spring.jpa.properties.org.hibernate.envers.revision_entity_name=com.yourpackage.CustomRevisionEntity

方案2:调整Envers默认修订ID生成策略

若不想自定义实体,可通过配置修改Envers默认的修订ID生成策略,使其兼容UUID:

# 指定修订ID生成器为UUID生成器
spring.jpa.properties.org.hibernate.envers.revision_id_generator_strategy=org.hibernate.id.UUIDGenerator
# 指定UUID生成策略(可选,默认即可)
spring.jpa.properties.org.hibernate.envers.revision_id_generator_params=uuid_gen_strategy_class=org.hibernate.id.uuid.CustomVersionOneStrategy

关键注意事项

  • 必须保留实体主键上的@Type(type="uuid-char")注解,确保Hibernate将UUID以字符串形式存入Varchar字段,避免二进制存储导致的编码错误。
  • 确保MariaDB方言配置正确:spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect

内容的提问来源于stack exchange,提问作者Hesam Karimian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 15:08:10