防止 Hibernate 对具有脏 OneToMany 集合的实体发出不必要的更新

Prevent Hibernate from issuing needless updates of entities that have dirty OneToMany Collection

我们将 Hibernate 5.3.13 与 Spring Data JPA 2.1.12 一起使用,并且当有一个已经持久化的、托管的最小实体时,如下所示:

@Entity
@Table(name = "EventsHolder")
@Access(AccessType.FIELD)
class EventsHolder {
    @LastModifiedDate
    @Column(name = "modifiedon", nullable = false)
    @Temporal(TIMESTAMP)
    @Access(AccessType.FIELD)
    Date modifiedOn;

    @Version
    @Column(name = "optlock", nullable = false)
    @Access(AccessType.FIELD)
    long optimisticLockingVersion = 0L;

    @Embedded
    Events events = new Events();

包含以下 Embeddable

@Embeddable
@Access(AccessType.FIELD)
class Events {

    @OneToMany(mappedBy = ...)
    @OrderBy("id ASC")
    @BatchSize(size = 10)
    List<Event> events = new LinkedList<>();

现在,每当调用 EventsHolder.events.add(...) 并添加到集合中的已持久托管事件时,休眠 - 在执行自动刷新时 - 将检测 EventsHolder.Events.events 集合在 org.hibernate.event.internal.DefaultFlushEntityEventListener#hasDirtyCollections 并将发出(不确定这是否是这里的重要先决条件)对 Spring Data 的 AuditingHandler 的预更新调用,这将更新 modifiedOn。

最后,optimisticLockingVersion 会递增,hibernate 发出更新语句,基本上只更新修改后的版本。

对于包含 5000 个事件的 EventsHolder,我们看到大约 4500-5000 的 optlock-versions 并且数据库的审计日志被所说的 "non-updates" 搅动,只更新修改后的版本和乐观锁定版本。

非常感谢任何关于如何阻止这种行为的想法。

通过删除间接 - 仅包含 @OneToMany 字段并将其直接内联到实体中的可嵌入 Events - 脏检查不再持续检测集合是否脏,一切都很好现在。