【问题标题】:Envers - How to propagate change of child-entity to parent?Envers - 如何将子实体的变化传播给父母?
【发布时间】:2022-08-24 21:59:22
【问题描述】:

我有以下设置:

@Entity
@Audited
public class House {

    @OneToOne(cascade = CascadeType.ALL)
    private Door frontDoor;
  
    // ...

}
@Entity
@Audited
public class Door {

    private String color;

    // ...

}

然后在我的代码中的其他地方以下几行:

// #1: Creation of house
var house = new House();
var door = new Door();
door.setColor(\"red\");
house.setFrontDoor(door);
houseRepository.save(door);

// #2: Modification of the front door
// (in another method)
var house = houseRepository.getById(/*...*/);
var door = house.getDoor();
door.setColor(\"blue\");
houseRepository.save(house);

所以我在审计表中得到的是这样的:

DOOR_AUD:

ID COLOR REV REVTYPE
1 red 1 0
1 blue 2 1

HOUSE_AUD:

ID FRONT_DOOR REV REVTYPE
2 1 1 0

但是,我需要HOUSE_AUD 中获得一个新条目 (就像我要修改house 中的直接/原始属性一样):

ID FRONT_DOOR REV REVTYPE
2 1 1 0
2 1 2 1

有没有办法告诉 Envers 为所有受影响的父母创建一个新的修订版?

    标签: java hibernate-envers


    【解决方案1】:

    所以,经过一些研究和测试,我在这里展示我的结果。

    我在这里遇到了类似的问题: How to Audit one-to-one relation through hibernate envers in bidirectional?

    我意识到我关于 hibernate 将其理解为父子关系的假设是错误的。 根据this answer@OneToOne 即使有级联,也不会使其成为单向定向关系。 有几种解决方法,我想作为功能参考我可能会在这里收集它们。

    解决方案 I:使用附加字段

    House 添加另一个字段,例如计数器或时间戳。

    临:这是一个非常直接的解决方法,并且易于理解。

    缺点:当您更新frontDoor 时,您需要确保每次都更新该字段。 此外,您需要扩展数据库表,并且实体会被纯技术污染事物.

    解决方案二:使用可嵌入

    @OneToOne 是否真的是您想要表达的那种关系可能值得考虑。也许Door 更适合作为@Embeddable

    临:你不需要关心其他任何事情。

    缺点:如果Door 将包含自己的@Embedded 字段,那么这可能根本就没有选择。此外,您可能已经在需要将其作为单独实体的不同上下文中使用Door

    解决方案三:使用条件审计

    没有尝试或看到有人这样做,但它可能会起作用......

    解决方案四:改变你的审计方法

    当您需要获取所有不同版本的列表时,也许您可​​以重新考虑您对审计内容的使用并检查(递归?)子实体中的修订。


    希望 Hibernate 团队将来会解决这个问题。但是,它看起来不太有希望:HHH-13362

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 1970-01-01
      • 2022-11-21
      • 1970-01-01
      • 2013-03-01
      • 2023-03-16
      相关资源
      最近更新 更多