如何让Envers将子实体变更同步至父实体审计记录?
问题描述
实体定义
@Entity @Audited public class House { @OneToOne(cascade = CascadeType.ALL) private Door frontDoor; // 其他属性和方法省略 }
@Entity @Audited public class Door { private String color; // 其他属性和方法省略 }
业务操作代码
// 1. 创建房屋及关联门 var house = new House(); var door = new Door(); door.setColor("red"); house.setFrontDoor(door); houseRepository.save(door); // 2. 修改门的颜色(另一个方法中执行) var house = houseRepository.getById(/* 房屋ID */); var door = house.getDoor(); door.setColor("blue"); houseRepository.save(house);
当前审计记录情况
DOOR_AUD(门的审计表):
| ID | COLOR | REV | REVTYPE |
|---|---|---|---|
| 1 | red | 1 | 0 |
| 1 | blue | 2 | 1 |
HOUSE_AUD(房屋的审计表):
| ID | FRONT_DOOR | REV | REVTYPE |
|---|---|---|---|
| 2 | 1 | 1 | 0 |
预期效果
希望修改门的颜色时,房屋的审计表也能生成一条新的修订记录,如下:
| ID | FRONT_DOOR | REV | REVTYPE |
|---|---|---|---|
| 2 | 1 | 1 | 0 |
| 2 | 1 | 2 | 1 |
即让Envers在子实体变更时,自动为受影响的父实体创建审计记录。
解决方案
要实现这个需求,你可以通过以下两种Envers配置方式达成:
方法一:给关联字段启用修改标记
在House类的frontDoor字段上,添加@Audited(withModifiedFlag = true)注解,明确让Envers跟踪这个关联字段的修改状态:
@Entity @Audited public class House { @OneToOne(cascade = CascadeType.ALL) @Audited(withModifiedFlag = true) private Door frontDoor; // 其他属性和方法省略 }
当关联的Door实体发生变更时,Envers会标记House的frontDoor字段为已修改,从而自动生成一条新的房屋审计记录。
方法二:通过@AuditMappedBy建立双向审计关联
如果你的实体是双向关联(可以给Door添加关联House的字段),可以使用@AuditMappedBy显式指定父实体的审计映射:
@Entity @Audited public class Door { private String color; @OneToOne(mappedBy = "frontDoor") @AuditMappedBy(mappedBy = "frontDoor") private House house; // 其他属性和方法省略 }
同时保持House类中frontDoor字段的@Audited配置,这样Envers会在Door修改时,同步触发House的审计记录生成。
注意事项
- 确保Hibernate Envers版本与你的Hibernate/JPA版本兼容,避免配置不生效。
- 修改操作必须在事务内执行(Spring环境下默认由
@Transactional管理),否则Envers无法捕捉到变更并生成审计记录。
内容的提问来源于stack exchange,提问作者leun4m
相关产品推荐
相关产品推荐

