Hibernate Enver:@AuditJoinTable 行缺失
Hibernate Enver : @AuditJoinTable rows missing
给定一个由 Envers 审计的实体,其中包含一个集合。
实体 A
@Audited
public class A{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
....
@OneToMany
@JoinColumn(name = "a_id")
@AuditJoinTable(name = "A_B_AUDIT"
,inverseJoinColumns = @JoinColumn(name = "a"))
private List<B> bs;
....
}
实体 B
@Audited
public class B{
@Id
private int id;
....
@Column(name = "a_id")
private int aId;
@ManyToOne
@JoinColumn(name = "a_id", insertable = false, updatable = false)
private A a;
}
根据他们的 documentation
Envers 将添加和删除的审计信息存储到这些 AuditJoinTables (A_B_AUDIT) 中。但不幸的是,这不起作用,表格中的行丢失了。
当我 运行 创建以下表格的项目时:
A_AUDIT
B_AUDIT
A_B_AUDIT
我有单独的控制器来持久化 A 对象和 B 对象。当我尝试使用 aId 和 A 保存 B 时,audit_table (A_B_AUDIT) 不会更新,但 B_AUDIT 更新修订版得到更新。
有人可以让我知道我在这里缺少什么吗。
谢谢!!
Hibernate Enver 版本:5.1.4.Final
如评论中所述,您的问题是您在单独的事务中执行这两个实体的持久化,但您没有建立正确的关联,因此您污染了 Hibernate 的一级缓存的状态.无意中,您还导致 Envers 无法正确审核您的实体,因为您没有为其提供所有正确的状态。
为了让这个用例与 Envers 一起工作,您需要修改处理实体持久性的方式 B
,因为它似乎是唯一 知道的东西 关于与实体的关系 A
。
在实体 B
的持久性期间,您可能应该这样做:
if ( b.getAId() != null ) {
A a = entityManager.find( A.class, b.getAId() );
a.getBs().add( b );
a = entityManager.merge( a );
b.setA( a );
entityManager.persist( b );
}
这意味着在实体 B
的持久化期间,您应该像您预期的那样在审计连接 table 中添加一个审计行,并且 Hibernate 一级缓存中的状态将包含所有两个实体之间的正确引用。
如果我们暂时搁置 Envers 并专注于正常的 JPA 提供程序使用,您应该能够在坚持 B 之后执行此操作并且它会起作用:
final A theA = b.getA();
assertNotNull( theA );
assertTrue( !theA.getBs().isEmpty() );
assertTrue( theA.getBs().contains( b ) );
显然,如果您不设置关联,这些断言(应该全部通过)将不会。它们唯一会通过的时间是您重新查询实体时 B
,但这不是必需的。
希望你明白。
给定一个由 Envers 审计的实体,其中包含一个集合。
实体 A
@Audited
public class A{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
....
@OneToMany
@JoinColumn(name = "a_id")
@AuditJoinTable(name = "A_B_AUDIT"
,inverseJoinColumns = @JoinColumn(name = "a"))
private List<B> bs;
....
}
实体 B
@Audited
public class B{
@Id
private int id;
....
@Column(name = "a_id")
private int aId;
@ManyToOne
@JoinColumn(name = "a_id", insertable = false, updatable = false)
private A a;
}
根据他们的 documentation Envers 将添加和删除的审计信息存储到这些 AuditJoinTables (A_B_AUDIT) 中。但不幸的是,这不起作用,表格中的行丢失了。
当我 运行 创建以下表格的项目时:
A_AUDIT
B_AUDIT
A_B_AUDIT
我有单独的控制器来持久化 A 对象和 B 对象。当我尝试使用 aId 和 A 保存 B 时,audit_table (A_B_AUDIT) 不会更新,但 B_AUDIT 更新修订版得到更新。
有人可以让我知道我在这里缺少什么吗。
谢谢!!
Hibernate Enver 版本:5.1.4.Final
如评论中所述,您的问题是您在单独的事务中执行这两个实体的持久化,但您没有建立正确的关联,因此您污染了 Hibernate 的一级缓存的状态.无意中,您还导致 Envers 无法正确审核您的实体,因为您没有为其提供所有正确的状态。
为了让这个用例与 Envers 一起工作,您需要修改处理实体持久性的方式 B
,因为它似乎是唯一 知道的东西 关于与实体的关系 A
。
在实体 B
的持久性期间,您可能应该这样做:
if ( b.getAId() != null ) {
A a = entityManager.find( A.class, b.getAId() );
a.getBs().add( b );
a = entityManager.merge( a );
b.setA( a );
entityManager.persist( b );
}
这意味着在实体 B
的持久化期间,您应该像您预期的那样在审计连接 table 中添加一个审计行,并且 Hibernate 一级缓存中的状态将包含所有两个实体之间的正确引用。
如果我们暂时搁置 Envers 并专注于正常的 JPA 提供程序使用,您应该能够在坚持 B 之后执行此操作并且它会起作用:
final A theA = b.getA();
assertNotNull( theA );
assertTrue( !theA.getBs().isEmpty() );
assertTrue( theA.getBs().contains( b ) );
显然,如果您不设置关联,这些断言(应该全部通过)将不会。它们唯一会通过的时间是您重新查询实体时 B
,但这不是必需的。
希望你明白。