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 如何处理架构更改?的主要内容,如果未能解决你的问题,请参考以下文章