使用休眠环境创建自定义修订实体时违反了完整性约束

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