Envers 如何处理架构更改?

Posted

技术标签:

【中文标题】Envers 如何处理架构更改?【英文标题】:How does Envers deal with schema changes? 【发布时间】:2011-08-11 12:06:23 【问题描述】:

我正在考虑从自行实现的版本控制解决方案切换到 Hibernate Envers,但我还不太确定。我已经阅读了很多关于它的内容,但我担心架构更改以及 Envers 在根据旧架构对历史数据进行处理后如何处理它们。

在这方面您对 Envers 有何经验?您如何使用 Envers 处理架构更改和现有数据?

更新 1:

这不仅仅是添加从表中删除简单的列,而是例如当将简单的外键关系更改为具有两个 1:n 关系的单独实体时(具有属性列的 M2M。这是数据模型中的“逻辑”更改。使用 Envers 时如何处理是否已经按照旧模型进行了历史数据?有没有一种替代方法可以手动编写 sql 脚本并将它们转换为新的表示形式?

【问题讨论】:

【参考方案1】:

根据我的经验,Envers 只是将实体表中的每个字段复制到其审计表中。审计表中复制的字段对它们没有任何约束,包括可空性和外键约束,因此在真实表上添加或删除此类约束没有问题。您添加到实体中的任何类型的关系都只是在 Envers 下添加的新审计列和/或表,您可以在其历史背景下正确解释它们。

对于您的示例,如果我理解正确,从基于连接列的关系切换到基于连接表的关系,您只需让旧连接列与连接表共存,此时在割接中,前者将不再被填充而有利于后者。您的历史记录将被完全保留,包括您进行此切换的事实。如果您希望所有旧数据都适合审计表中的新模型,则由您来执行迁移。

【讨论】:

【参考方案2】:

修改现有架构应该没有问题,因为 Envers 依赖于您的 @Entities 来创建审计表。因此,如果您从现有表中添加或删除列,只要此更改反映在您的 @Entity / @Audited JavaBean 中,就应该没问题。

【讨论】:

谢谢!根据您的回复更新问题。 我还不明白这不是问题吗?例如,如果我有一列,它将被删除并替换为两列。实体已更新,我更新了历史表以包含 2 个新列,但是历史表中删除的列会发生什么情况?是否应该删除它,并操纵历史?它是否应该保留并让历史表在每次操作时无限增长?这不是编译错误的问题,因为它当然会编译和工作。【参考方案3】:

外键重构应该可以使用 Envers。由于 Envers 甚至为一对多关系创建了一个连接表,因此应该直接将其更改为多对多关系。我从official document中提取了一段:

9.3。 @OneToMany+@JoinColumn

当使用这两个注解映射集合时,Hibernate 不生成连接表。然而,Envers 必须这样做,所以 当您阅读相关实体具有的修订版时 改变了,你不会得到错误的结果。

为了能够命名附加连接表,有一个特殊的 注释:@AuditJoinTable,与 JPA 的语义相似 @JoinTable。

一种特殊情况是使用@OneToMany+@JoinColumn 映射的关系 一方面,@ManyToOne+@JoinColumn(insertable=false, 可更新=假)在许多方面。这样的关系实际上是 双向,但拥有方是集合(参见此处)。

要正确审核与 Envers 的此类关系,您可以使用 @AuditMappedBy 注释。它使您能够指定相反的 属性(使用 mappedBy 元素)。在索引集合的情况下, 索引列也必须映射到被引用的实体中(使用 @Column(insertable=false, updatable=false),并指定使用 位置映射。此注释只会影响 Envers 的方式 作品。请注意,注释是实验性的,可能会改变 未来。

【讨论】:

以上是关于Envers 如何处理架构更改?的主要内容,如果未能解决你的问题,请参考以下文章

如果使用 sorm,如何处理架构更改

放弃 Hibernate Envers 中的修订

如何处理派生类的多个重载而不需要对其他文件进行多次更改

如何处理 BQ GA 导出更改?

AWS postgres RDS 读取复制如何处理架构切换?

如何处理 Android 应用程序中的版本更改