使用休眠环境创建自定义修订实体时违反了完整性约束
Integrity constraint violated when creating custom revision entity with hibernate envers
我有一个应用程序使用 hibernate envers 并对一些实体进行审计。
我想在审核 table 中添加一些额外的列,并遵循我在多个博客中找到的标准说明。
首先我创建了一个自定义修订实体:
@Entity
@RevisionEntity(UserRevisionListener.class)
public class UserRevEntity extends DefaultRevisionEntity {
private String username;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
}
然后修改监听器:
public class UserRevisionListener implements RevisionListener {
@Override
public void newRevision(Object revisionEntity) {
UserRevEntity exampleRevEntity = (UserRevEntity) revisionEntity;
exampleRevEntity.setUsername("TEST");
}
}
问题是,当应用程序保存一个实体(我们称之为 MyEntity)时,它违反了数据库的外键约束。
我得出的结论是,到目前为止,envers 已写入 REVINFO table,但现在通过查看 JPA 发送到数据库的查询,我发现它写入了 USERREVTABLE。因为 MyEntity 被持久化的 table 有一个引用 REVINFO 的外键约束,它会导致约束冲突。
我该如何解决这个问题?是否有任何 envers 注释来解决这种情况?
请帮忙,提前致谢。
最简单的解决方案就是这样做
@Entity
@Table(name = "REVINFO")
@RevisionEntity(UserRevisionListener.class)
public class UserRevEntity extends DefaultRevisionEntity {
...
}
如果你注意到了,我已经明确地添加了一个 @Table
注释来解决这个问题。
您 运行 使用自定义修订实体的原因与实体发现有很大关系。
在您不提供自定义修订实体的默认情况下,Envers 实际上使用 class 并手动将 class 映射为 Hibernate XML 映射中的实体配置。在该默认情况下,我们明确告诉 ORM class 的支持 table 是 REVINFO
.
当您提供自己的自定义修订实体时,该实体映射实际上首先由 ORM 发现,因为它是您域模型中的真实实体。这意味着 Envers 必须检查 ORM 在 bootstrap 期间拥有的实体映射,如果发现 @RevisionEntity
,那么我们不会提交具有默认配置的 Hibernate XML 映射。
副作用是 ORM 已经确定了来自您的自定义修订实体的所有映射数据的 table-名称、实体名称、列名称等,这些是我们在其中的属性技术上无法在 bootstrap 发生时进行更改,该数据已经被正常的 ORM bootstrap 流程绑定。
因此,如果您想将自定义修订实体覆盖在默认 table 上,并根据需要添加一个新列来简单地更改它;您需要在自定义实体映射的注释中明确说明并强制 ORM 使用特定的 table-name 否则它将使用默认的命名策略策略,这正是您开始看到它使用 UserRevEntity
而不是 REVINFO
.
添加 @Table(name = "REVINFO")
,它将像往常一样插入 REVINFO
。
我有一个应用程序使用 hibernate envers 并对一些实体进行审计。
我想在审核 table 中添加一些额外的列,并遵循我在多个博客中找到的标准说明。
首先我创建了一个自定义修订实体:
@Entity
@RevisionEntity(UserRevisionListener.class)
public class UserRevEntity extends DefaultRevisionEntity {
private String username;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
}
然后修改监听器:
public class UserRevisionListener implements RevisionListener {
@Override
public void newRevision(Object revisionEntity) {
UserRevEntity exampleRevEntity = (UserRevEntity) revisionEntity;
exampleRevEntity.setUsername("TEST");
}
}
问题是,当应用程序保存一个实体(我们称之为 MyEntity)时,它违反了数据库的外键约束。
我得出的结论是,到目前为止,envers 已写入 REVINFO table,但现在通过查看 JPA 发送到数据库的查询,我发现它写入了 USERREVTABLE。因为 MyEntity 被持久化的 table 有一个引用 REVINFO 的外键约束,它会导致约束冲突。
我该如何解决这个问题?是否有任何 envers 注释来解决这种情况?
请帮忙,提前致谢。
最简单的解决方案就是这样做
@Entity
@Table(name = "REVINFO")
@RevisionEntity(UserRevisionListener.class)
public class UserRevEntity extends DefaultRevisionEntity {
...
}
如果你注意到了,我已经明确地添加了一个 @Table
注释来解决这个问题。
您 运行 使用自定义修订实体的原因与实体发现有很大关系。
在您不提供自定义修订实体的默认情况下,Envers 实际上使用 class 并手动将 class 映射为 Hibernate XML 映射中的实体配置。在该默认情况下,我们明确告诉 ORM class 的支持 table 是 REVINFO
.
当您提供自己的自定义修订实体时,该实体映射实际上首先由 ORM 发现,因为它是您域模型中的真实实体。这意味着 Envers 必须检查 ORM 在 bootstrap 期间拥有的实体映射,如果发现 @RevisionEntity
,那么我们不会提交具有默认配置的 Hibernate XML 映射。
副作用是 ORM 已经确定了来自您的自定义修订实体的所有映射数据的 table-名称、实体名称、列名称等,这些是我们在其中的属性技术上无法在 bootstrap 发生时进行更改,该数据已经被正常的 ORM bootstrap 流程绑定。
因此,如果您想将自定义修订实体覆盖在默认 table 上,并根据需要添加一个新列来简单地更改它;您需要在自定义实体映射的注释中明确说明并强制 ORM 使用特定的 table-name 否则它将使用默认的命名策略策略,这正是您开始看到它使用 UserRevEntity
而不是 REVINFO
.
添加 @Table(name = "REVINFO")
,它将像往常一样插入 REVINFO
。