SpringBoot中Liquibase(ddl-auto=none)结合Hibernate-envers无审计数据求助
问题背景
SpringBoot项目中使用Liquibase管理数据库结构,设置spring.jpa.hibernate.ddl-auto=none,手动通过Liquibase执行了包含revinfo、resources_aud等审计表的SQL脚本。引入Hibernate Envers后,对Resource、SupportProgram实体执行增删改操作,审计表中未生成对应数据。
排查与解决步骤
1. 确认实体已开启审计注解
需要确保目标实体类及需审计的关联字段添加了@Audited注解:
@Entity @Audited // 开启该实体全局审计 public class Resource { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private LocalDateTime createdAt; @ManyToOne @Audited // 关联字段需审计时添加此注解 private SupportProgram supportProgram; // getter/setter 省略 }
2. 确保Envers自动配置生效
ddl-auto=none场景下,显式配置Envers核心参数避免监听器未注册:
spring: jpa: properties: hibernate: envers: autoRegisterListeners: true # 强制开启审计监听器注册 audit_table_suffix: _aud # 与手动创建的审计表后缀保持一致
3. 修正审计表结构匹配Envers预期
检查revinfo表的主键生成规则,Envers默认需要自增的rev值:
-- 修改原revinfo表的rev字段为自增主键 CREATE TABLE revinfo ( rev integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, revtstmp bigint NOT NULL, user_id bigint, CONSTRAINT fk_revinfo_user_id_users_id FOREIGN KEY (user_id) REFERENCES users(id) );
其他审计表(如resources_aud)的字段类型、外键关联需与主表及Envers要求匹配,你的现有脚本中字段类型是符合要求的。
4. 确认操作在事务中执行
Envers审计逻辑绑定事务,需保证增删改方法被@Transactional注解修饰:
@Service public class ResourceService { @Autowired private ResourceRepository resourceRepository; @Transactional // 必须在事务内执行,Envers才会生成审计数据 public Resource saveResource(Resource resource) { return resourceRepository.save(resource); } }
5. 检查Liquibase脚本执行顺序
确保创建审计表的脚本在主表(resources、support_programs)创建之后执行,避免外键关联失败导致审计数据无法写入。
6. 开启日志排查细节
添加日志配置,查看Envers是否触发审计SQL:
logging: level: org.hibernate.SQL: DEBUG org.hibernate.envers: DEBUG # 专门打印Envers相关日志
如果日志中无revinfo和xxx_aud表的插入SQL,说明监听器未触发,需回头检查配置。
自定义RevisionEntity注意事项
如果扩展了DefaultRevisionEntity(比如添加user_id字段),需确保自定义监听器正确注册:
@Entity @RevisionEntity(CustomRevisionListener.class) public class CustomRevisionEntity extends DefaultRevisionEntity { private Long userId; // getter/setter 省略 } public class CustomRevisionListener implements RevisionListener { @Autowired private AuthenticationFacade authenticationFacade; @Override public void newRevision(Object revisionEntity) { CustomRevisionEntity customRevision = (CustomRevisionEntity) revisionEntity; User currentUser = authenticationFacade.getCurrentUser(); if (currentUser != null) { customRevision.setUserId(currentUser.getId()); } } }
内容的提问来源于stack exchange,提问作者Kitovraz
相关产品推荐
相关产品推荐

