我遇到了同样的问题。我使用 Hibernate Interceptor 修复了它。
首先,您必须在基础实体类中声明一些基础方法,以便我们找到实体的父级,这是一个链接更新所需字段的方法。
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 拦截器来强制更新脏实体的所有父级。
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
spring.jpa.properties.hibernate.ejb.interceptor=com.your.package.EntityChainForceUpdateHibernateInterceptor
这是一个如何覆盖getParent()的示例。
@MappedSuperclass
public abstract class BaseEntity {
@Column(name = "last_updated_at")
private Instant lastUpdatedAt;
public Optional<BaseEntity> getParent() {
return Optional.empty();
}
public void updateChain() {
this.lastUpdatedAt = Instant.now();
this.getParent().ifPresent(p -> p.updateChain());
}
}
@Entity
public class ParentEntity extends BaseEntity {
@Id
@Column(name = "id")
private String id;
@Column(name = "something")
private String somethingToUpdateWhenChildSaved;
@Override
public void updateChain() {
this.somethingToUpdateWhenChildSaved = "anything";
super.updateChain();
}
}
@Entity
public class ChildEntity extends BaseEntity {
@ManyToOne
@JoinColumn(name = "parent_id", referencedColumnName = "id")
private ParentEntity parent;
@Override
public Optional<BaseEntity> getParent() {
return Optional.of(this.parent);
}
}