如果没有从父存储库中显式刷新,则对父的修改不会持久

时间:2018-09-11 09:06:59

标签: java hibernate jpa spring-data-jpa spring-data

使用spring-data-jpa 2.0.8.RELEASE

我有一个@OneToMany相关实体对。假设KingPeasant。我希望有一个逻辑,当更新农民时,这也会手动更新国王@LastModifiedDate的值。我做这样的事;

@PreUpdate
@PreRemove
@PrePersist
void updateParents() {
    Date now = new Date();
    BaseEntity container = getParent();
    while (Objects.nonNull(container)) {
        container.setUpdateDateTime(now);
        container = container.getParent();
    }
}

,并且效果很好,这意味着它确实将所有父母更新为国王(表结构确实混乱,从国王到最低农奴的深度为5),我遇到的问题是,对父母的修改不是坚持不懈。我有以下服务;

@Transactional
public void update(String kingId, String peasantSeqNo) {
    Peasant peasant = peasantRepository.getPeasant(kingId, peasantSeqNo);
    peasant.setNobility(false);
    peasantRepository.save(peasant);
}

在上面的代码中,触发了@PreUpdate注释的updateParents()方法,并且国王的更新时间戳也被更新,即使在事务结束之后,该更改也不会持久。我可以使用显式的kingRepository.flush()来触发这种持久性,但是我希望可以自动完成,只需修改父级即可。

国王农民之间的联系如下;

@JsonManagedReference
@OneToMany(mappedBy = "parent", cascade = REMOVE)
private List<Peasant> peasantry;

@JsonBackReference
@MapsId("kingId")
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "ID_KING", referencedColumnName = "ID_KING", nullable = false)
private King parent;

这在某种程度上影响了我对JPA的使用,但是找不到确切的原因和解决方案,您能对此提供任何意见吗?

1 个答案:

答案 0 :(得分:1)

您遇到了JPA(实施)的限制。

事件触发后,JPA实现已经决定了它将保留的实体,因此您的更改不会被提取。

此行为实际上定义为未在JPA规范中定义:

  

通常,可移植应用程序的生命周期方法不应调用EntityManger或查询操作,访问其他实体实例或在同一持久性上下文中修改关系[46]。[47]生命周期回调方法可能会修改在其上调用它的实体的非关系状态。

     

[46]请注意,此警告还适用于可能注入到实体侦听器中的对象的操作。

     

[47]此类操作的语义可能会在此规范的将来版本中进行标准化。

因此,您需要将此行为从JPA监听器转移到业务逻辑中。