@PreUpdate在更新时不会保存父对象 [英] @PreUpdate doesn't save parent object when it's updated

查看:119
本文介绍了@PreUpdate在更新时不会保存父对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个关系一对多的实体. Parent 可以有几个 Child 实体实例.我向父级添加了一个字段,用于存储子级修改的日期( childrenLastModifiedDate ).为了保持这一点,我添加了方法:

I have two entities with relation one to many. Parent can have several Child entity instances. I added a field to the parent that stores the date of children modifications(childrenLastModifiedDate). To maintain that, I added method:

@PrePersist
@PreUpdate
@PreRemove
private void handle() {
    parent.setChildrenLastModifiedDate(now());
}

这是问题所在.保存子项时,它并不总是调用.在本地(mac os),它可以按预期工作,跟踪所有三种类型的更改并将其保存到父实体.但是,在服务器(linux)上,它仅适用于:

Here is the problem. It's not always invoke when the child is saved. Locally(mac os), it works as expected, all three types of changes are tracked and saved to the parent entity. However, on the server(linux) it only works for:

  • @PrePersist
  • @PreRemove

即使调用PreUpdate,也不会保存更改.我什至尝试添加直接存储库调用来保存父级.结果是一样的.更新时不保存任何内容,但删除或保留时保存任何内容.我试图在其他事务中进行此更改,并且此更改有效,但是这太浪费资源了.另外,我可以看到有人也有非常相似的经历:

Even though, PreUpdate is invoked, the changes are not saved. I have even tried to add a direct repository call to save the parent. The result is the same. Nothing is saved on update, but saved on remove or persist. I tried to make this change in additional transaction and it worked, but it's too resource consuming. Also, I can see that someone had very similar experience:

JPA/休眠preUpdate不会更新父对象

但是,如何处理问题本身没有任何内容.问题是:是否有办法保证使用此批注将始终有效并执行从属实体的其他更新?如果不是,处理这种逻辑的最佳方法是什么?对孩子的每次更改都需要更新.即使通过级联保存.

However, there is nothing on how to handle the problem itself. The question is: is there a way to guarantee that using of this annotations will always work and perform additional updates of dependent entities? If it's not, what is the best way to handle such logic? The update is required on each change to children. Even if it is saved by cascade.

推荐答案

我遇到了同样的问题.我通过使用休眠拦截器对其进行了修复.

I got the same problem. I fixed it by using Hibernate Interceptor.

首先,您必须在基本实体类中声明一些基本方法,该基本方法使我们能够找到实体的父代,这是用于链接更新所需字段的方法.

First, you have to declare some base method in the base entity class that allow us to find the parent of an entity, an a method to chaining update your desired fields.

public abstract class BaseEntity {
    public Optional<BaseEntity> getParent() {
        // subclass should override this method to return the parent entity
        return Optional.empty();
    }
    public void updateChain() { 
        // update your desired fields
        ...
        this.getParent().ifPresent(p -> p.updateChain());
    }
}

然后,您可以使用以下Hibernate拦截器强制更新脏实体的所有父代.

Then you can use following Hibernate interceptor to force update all parents of the dirty entities.

public class EntityChainForceUpdateHibernateInterceptor extends EmptyInterceptor {

    @Override
    public void preFlush(Iterator entities) {
        entities.forEachRemaining(e -> {
            if (BaseEntity.class.isAssignableFrom(e.getClass())) {
                BaseEntity b = (BaseEntity) e;
                b.getParent().ifPresent(p -> p.updateChain());
            }
        });
    }
}

要在Spring中注册此拦截器,只需将以下行添加到 application.properties

To register this interceptor with Spring, just add following line to application.properties

spring.jpa.properties.hibernate.ejb.interceptor=com.your.package.EntityChainForceUpdateHibernateInterceptor

这篇关于@PreUpdate在更新时不会保存父对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆