Hibernate Envers在@ManyToOne关联下未正确存储关联列值问题
嘿,这个Envers的问题我之前也碰到过,来给你拆解一下~
首先说为什么会出现这个情况:Envers对@ManyToOne关联的默认审计逻辑,是存储关联实体的主键ID(也就是你的Machine.id),而不是你在@JoinColumn里指定的外键列值(machineCode)。哪怕你的外键关联的是Machine.machineCode而非主键,Envers依然会优先用实体主键来记录关联关系,这是它的默认行为。
你不想加@OneToMany是完全合理的——双向关联不仅会让Envers额外审计集合的变化,还可能带来不必要的加载开销,能避免就避免。
那怎么解决呢?给你个简单可行的方案,不用改关联关系,也不用加额外的双向映射:
方案:在Device中添加冗余的machineCode字段并让Envers审计它
你可以直接在Device里映射数据库中已经存在的machineCode列,然后让Envers审计这个字段,同时告诉Envers不要审计原来的machine关联字段。这样审计表就会存储machineCode的实际值,而不是Machine的ID。
修改后的Device实体代码大概是这样:
@Audited @Entity(name = "device") @Table(name = "device") public class Device { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 告诉Envers不要审计这个关联字段 @NotAudited @ManyToOne(optional = false, fetch = FetchType.LAZY) @JoinColumn(name = "machineCode", referencedColumnName = "machineCode") private Machine machine; // 直接映射到数据库的machineCode列,让Envers审计这个值 @Column(name = "machineCode") private String machineCode; // 用生命周期注解自动同步machineCode,避免手动维护出错 @PrePersist @PreUpdate private void syncMachineCode() { if (machine != null) { this.machineCode = machine.getMachineCode(); } } // 剩下的getter、setter自己补上就行 }
为什么这个方案可行?
@NotAudited会让Envers忽略掉machine关联字段的审计,不会再把Machine.id写到审计表里- 新增的
machineCode字段直接映射到数据库中Device表的外键列,Envers会正常审计这个字段的实际值 @PrePersist和@PreUpdate注解会在保存/更新Device时自动同步machineCode的值,不用你手动在业务代码里维护,保证了数据一致性
这样既解决了审计表存储值不对的问题,又避免了添加@OneToMany带来的额外开销,完美适配你的需求~
内容的提问来源于stack exchange,提问作者mohitSehgal
相关产品推荐
相关产品推荐

