当前位置: 首页 > 知识库问答 >
问题:

Hibernate envers-加载嵌套对象的历史记录

傅振濂
2023-03-14

我有一个实体,它有一些列表,看起来像这样:

@Entity
@Table(name = "HOME")
@Audited
public class House {

    @Id
    private Integer id;

    @Version
    @Column(name = "UPDATE_DATE", nullable = false)
    private Date updateDate;

    @Column(name = "DESCRIPTION", nullable = false)
    private String description;

    @Cascade(CascadeType.ALL)
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "home", orphanRemoval = true)
    private Set<Room> rooms;

    [...]

}

还假设房间实体如下所示:

@Entity
@Table(name = "ROOM")
@Audited
public class Room {

    @Id
    private Integer id;

    @Version
    @Column(name = "UPDATE_DATE", nullable = false)
    private Date updateDate;

    @Column(name = "NAME", nullable = false)
    private String name;

    @Cascade(CascadeType.ALL)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="HOUSE", nullable=false)
    private House house;

    [...]

}

如您所见,房间是通过级联保存的。让我们进入我问题的核心。。。

预告:

内部对象中的当前数据:

House:
    description: "red house"
    rooms: [room1, room2]

已审核表中的当前数据:

--- HOUSE_A ---
| REV | REVTYPE | ID | UPDATE_DATE     | DESCRIPTION |
+-----+---------+----+-----------------+-------------+
| 111 | 0       | 10 | 2015-08-3 12:00 | red house   |

--- ROOM_A ---
| REV | REVTYPE | ID  | UPDATE_DATE     | NAME  | HOUSE |
| 111 | 0       | 100 | 2015-08-3 12:00 | room1 | 10    |
| 111 | 0       | 110 | 2015-08-3 12:00 | room2 | 10    |

用户步骤:

使用这些数据更新房屋对象(更改房屋说明):

House:
    description: "blue house"
    rooms: [room1, room2]

执行此操作后,已审核的表将如下所示:

--- HOUSE_A ---
| REV | REVTYPE | ID | UPDATE_DATE     | DESCRIPTION  |
+-----+---------+----+-----------------+--------------+
| 111 | 0       | 10 | 2015-08-3 12:00 | red house    |
| 112 | 1       | 10 | 2015-08-3 12:30 | blue house   |

--- ROOM_A ---
| REV | REVTYPE | ID  | UPDATE_DATE     | NAME  | HOUSE |
| 111 | 0       | 100 | 2015-08-3 12:00 | room1 | 10    |
| 111 | 0       | 110 | 2015-08-3 12:00 | room2 | 10    |

使用这些数据更新房屋对象(不要更改房屋对象并添加一个房间):

House:
    description: "blue house"
    rooms: [room1, room2, room3]

执行此操作后,已审核的表将如下所示:

--- HOUSE_A ---
| REV | REVTYPE | ID | UPDATE_DATE     | DESCRIPTION  |
+-----+---------+----+-----------------+--------------+
| 111 | 0       | 10 | 2015-08-3 12:00 | red house    |
| 112 | 1       | 10 | 2015-08-3 12:30 | blue house   |

--- ROOM_A ---
| REV | REVTYPE | ID  | UPDATE_DATE     | NAME  | HOUSE |
| 111 | 0       | 100 | 2015-08-3 12:00 | room1 | 10    |
| 111 | 0       | 110 | 2015-08-3 12:00 | room2 | 10    |
| 113 | 0       | 120 | 2015-08-3 12:40 | room3 | 10    |

加载审计房屋数据:

--- current result ---
HOUSE_A(last_rev) -> HOUSE_A(112) -> 'blue house' with room1 and room2

--- expected result ---
HOUSE_A(last_rev) -> HOUSE_A(113) -> 'blue house' with room1, room2 and room3

这就是问题所在...

house的最高版本是112,但我完成的最后一个操作已与版本113一起保存(由于house对象未更改,所以版本条目未添加到house_A)。我知道envers会为修订较少或相等的house对象加载所有数据。在这种情况下,不会加载最后一个操作。问题是-加载此类操作(主对象未更新)的唯一方法是在保存之前更新主对象(房屋)的上次更新日期,以便新条目将以与房屋A中相同的版本添加到房屋A中?

在这个变通方法之后,审计的表将看起来像这样...

--- HOUSE_A ---
| REV | REVTYPE | ID | UPDATE_DATE      | DESCRIPTION  |
+-----+---------+----+------------------+--------------+
| 111 | 0       | 10 | 2015-08-30 12:00 | red house    |
| 112 | 1       | 10 | 2015-08-30 12:30 | blue house   |
| 113 | 1       | 10 | 2015-08-30 12:40 | blue house   |

--- ROOM_A ---
| REV | REVTYPE | ID  | UPDATE_DATE      | NAME  | HOUSE |
+-----+---------+-----+------------------+-------+-------+
| 111 | 0       | 100 | 2015-08-30 12:00 | room1 | 10    |
| 111 | 0       | 110 | 2015-08-30 12:00 | room2 | 10    |
| 113 | 0       | 120 | 2015-08-30 12:40 | room3 | 10    |

共有1个答案

牟星火
2023-03-14

你没有提到你正在使用的Envers版本,但是在Envers 5. x中默认启用了一个配置属性,它应该会触发这个确切的功能:

org.hibernate.envers.revision_on_collection_change=true

由于Room拥有与Home的关系,因此启用此配置将导致Envers在Room集合修改时记录Home的修订更改。

 类似资料:
  • 问题内容: 我试图遍历嵌套对象以检索由字符串标识的特定对象。在下面的示例对象中,标识符字符串是“ label”属性。我无法解决如何遍历树以返回适当对象的问题。任何帮助或建议,将不胜感激。 问题答案: 您可以创建像这样的递归函数来对对象进行深度优先遍历。 可以这样称呼

  • 问题内容: 我目前有这个: test.json看起来像这样: 我越来越: 如何更改它,以便无论我拥有多少嵌套值,它都将循环遍历所有嵌套项目? 所以对于上面的例子,我会得到 问题答案: 您可以创建一个递归循环函数,但是会遇到一个问题:当属性是对象时,因为没有字符串,所以没有文本可显示。因此,您将得到: 因为while 是为项目#2显示的字符串,所以它是为项目#1显示的对象。 无论如何,这就是我组成的

  • 问题内容: 我必须遍历json数组对象。 它具有以下结构。 基本上我在做的是prod_1是产品的名称,并且prod_1的版本列表已填充在其中。 所以现在我想要的是产品的名称以及它的版本。 问题在于可能有很多产品和该产品下的许多版本。所以我需要可以在 javascript 中使用适当的循环结构来对其进行处理。 最好将循环将产品名称存储在一个变量中,将版本存储在另一个变量中,因为我需要对产品名称进行一

  • 读取播放历史信息 调用地址 http://api.bilibili.cn/history 返回 返回值字段 字段类型 字段说明 results int 返回的记录总数目 list object 返回数据 返回字段 “list” 子项 返回值字段 字段类型 字段说明 aid int 视频编号 typeid int 视频分类ID typename string 视频分类名称 title string

  • 历史记录 控制台维护 Elasticsearch 成功执行的最后500个请求列表。点击窗口右上角的时钟图标即可查看历史记录。这个图标会打开历史记录面板,您可以在其中查看历史请求。您也可以在这里选择一个请求,它将被添加到编辑器中当前光标所在的位置。 图 9. 历史记录面板

  • 3.3.1.1. 同步的文件历史记录 微力同步记录对文件的添加,修改、删除的操作记录,通过历史记录列表可查看时间时间及发生设备,如下: 事件时间,显示添加、修改、删除等操作发生的时间; 文件时间,显示该文件的最后修改时间; 操作类型,显示此次针对该文件所进行的操作的类型; 发生设备,显示进行此操作的设备名称; 目录,显示该文件所属同步目录; 清空历史记录,点击后可清除所有记录,此操作仅清除记录而已