使用Hibernate Envers创建自定义修订版实体时违反了完整性约束

时间:2018-12-12 14:17:39

标签: sql hibernate jpa hibernate-envers

我有一个使用休眠envers的应用程序,并且对某些实体进行了审核。

我想在审核表中添加一些额外的列,并遵循我在多个博客中找到的标准说明。

首先,我创建了一个自定义修订版实体:

   <div class="row">
    <div class="form-group">
        <label class="control-label col-sm-1" for="employees">
            <h5>Workforce <span style="color:red">*</span></h5>
        </label>
        <div class="col-sm-2">
            <div class="form-group">
                @Html.DropDownListFor(x => x.company.employees, ViewBag.employees as IEnumerable<SelectListItem>,
                             "Select employees",
                             new { @class = "form-control", @id = "employees", onchange = "employees(this.value)" })
                @Html.ValidationMessageFor(m => m.company.employees, "", new { @class = "text-danger" })
            </div>
        </div>
    </div>
</div>

然后是修订侦听器:

@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; }
}

问题在于,当应用程序保存一个实体(我们称其为MyEntity)时,它违反了数据库上的外键约束。

我得出的结论是,到目前为止,envers都已写入REVINFO表中,但是现在通过查看JPA发送到数据库的查询,我看到它写入了USERREVTABLE。由于MyEntity持久化的表具有引用REVINFO的外键约束,因此会导致约束冲突。

我该如何克服这个问题?是否有任何envers注释可解决此问题?

请帮助,谢谢。

1 个答案:

答案 0 :(得分:1)

最简单的解决方案是这样做

@Entity
@Table(name = "REVINFO")
@RevisionEntity(UserRevisionListener.class) 
public class UserRevEntity extends DefaultRevisionEntity {
  ...
}

如果您注意到了,我已经明确添加了@Table注释来解决该问题。

使用自定义修订实体遇到此问题的原因与实体发现有很大关系。

在不提供自定义修订实体的默认情况下,Envers实际上使用一个类,并在Hibernate XML映射配置中手动将该类映射为实体。在这种默认情况下,我们明确告诉ORM该类的支持表是REVINFO

当您提供自己的自定义修订实体时,ORM首先会发现该实体映射,因为它是域模型中的真实实体。这意味着Envers必须在引导过程中检查ORM所具有的实体映射,并且如果使用@RevisionEntity找到了实体映射,那么我们就不会使用默认配置提交Hibernate XML映射。

副作用是ORM从您的自定义修订实体中确定了所有映射数据的表名,实体名,列名等内容,这些是我们无法在技术上进行更改的属性该引导程序发生的时间点是,数据已被正常的ORM引导程序进程绑定。

因此,如果要将自定义修订实体覆盖在默认表上,只需添加所需的新列即可对其进行更改;您需要在自定义实体映射上的注释中明确显示,并强制ORM使用特定的表名,否则它将使用默认的命名策略策略,这正是您开始使用UserRevEntity看到它的原因而不是REVINFO

添加@Table(name = "REVINFO"),它将像往常一样插入REVINFO中。