Spring Boot 3集成Envers审计删除实体触发created_by非空约束异常
Spring Boot 3集成Envers与JPA审计功能,实体创建、编辑时审计正常,created_by等字段能正确填充到主表及审计表;但执行删除操作时,触发数据库非空约束错误:
org.springframework.dao.DataIntegrityViolationException: could not execute statement [ERROR: null value in column "created_by" of relation "price_item_aud" violates not-null constraint Detail: Failing row contains (356, 2, 8ca32c7d-d087-49b9-be0a-1158bb105ff9, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null).]
删除时AuditorAware未被调用,当前使用的Envers特殊配置:
audit_strategy: "org.hibernate.envers.strategy.ValidityAuditStrategy" audit_strategy_validity_store_revend_timestamp: true
检查删除操作的触发方式
如果使用原生SQL、JPQL批量删除(如带@Modifying注解的自定义查询),Spring Data JPA的审计切面不会自动拦截这类操作,导致AuditorAware不被调用,同时Envers无法从实体中获取created_by等历史审计字段。尝试改用JPA原生的deleteById()或delete()方法删除单个实体,验证是否能触发审计。验证ValidityAuditStrategy的行为逻辑
该策略通过维护rev和revend的有效区间记录审计历史,正常情况下删除操作应更新原审计记录的revend字段,而非插入新记录。若日志显示插入新的price_item_aud记录,可能是Hibernate 6(Spring Boot 3对应版本)中该策略的行为有变动,或实体映射存在冲突。可临时切换为默认的DefaultAuditStrategy测试,排查是否为策略本身的问题。检查实体审计字段的加载状态
删除操作若未加载实体的完整数据(如懒加载未触发、仅执行删除SQL未查询实体),Envers无法获取created_by等已存在的审计字段值,导致插入审计记录时字段为空。确保删除前先通过findById()查询实体,再执行删除操作,让Envers能读取到实体的完整审计信息。核对审计字段的非空约束配置
若实体中created_by等字段标注了@Column(nullable = false),生成的审计表会同步该约束,但Envers在删除场景下可能不会自动填充这些历史字段。可临时修改审计表的非空约束为允许空(仅用于测试),或配置Envers在删除时复用原审计记录的字段值。检查事务与审计切面的兼容性
删除操作若未处于Spring事务管理范围内,Envers的审计回调可能无法触发。确保删除方法标注了@Transactional,且事务传播行为符合预期(如默认的REQUIRED)。排查Spring Boot 3与Envers版本适配问题
Spring Boot 3依赖Hibernate 6.x,Envers作为Hibernate的子模块,部分旧版配置或行为在新版本中有所调整。核对官方文档,确认ValidityAuditStrategy的配置是否符合Hibernate 6的要求。
内容的提问来源于stack exchange,提问作者Softwaregarden

