gpt4 book ai didi

java - Hibernate 在设置父级后尝试两次保留子级

转载 作者:行者123 更新时间:2023-11-30 06:44:15 24 4
gpt4 key购买 nike

我有这样的 Hibernate 映射:

父级:

@OneToMany(mappedBy = "parent")
@Valid
private Set<Assignment> assignments;

child :

@ManyToOne(cascade = {CascadeType.PERSIST})
@JoinColumn(name = "parent_id")
@Valid
private Parent parent;

我遇到了这样的情况:父项已经保存在数据库中,我得到了新的作业列表。我做了这样的事情(使用 Spring Data JPA):

parent.getAssignments().addAll(newAssignments);
parent.getAssignments().forEach(assignment -> assignment.setParent(parent));
parentRepository.save(parent);

我在基本实体中有@PrePersist注释的方法(由两者扩展),并通过验证检查在@PrePersist中初始化的createdDate是否不为空。基础实体包含:

@NotNull
@Column(name = "created_date")
protected LocalDateTime createdDate;

@PrePersist
public void prePersist() {
setCreatedDate(LocalDateTime.now());
setModifiedDate(LocalDateTime.now());
validateEntity();
}

private void validateEntity() {
Set<ConstraintViolation<BaseEntity>> violations = Validation.buildDefaultValidatorFactory().getValidator().validate(this);
if(!violations.isEmpty()) {
throw new RuntimeException(new ValidationMessageBuilder().build(violations));
}
}

我检查了调试器下的对象,例如Assignment是对象@17609,Parent是@17608。

调用 save() 方法后引发异常。

java.lang.RuntimeException: may not be null => com.foo.bar.model.domain.Assignment.parent.assignments.createdDate.
at com.foo.bar.model.BaseEntity.validateEntity(BaseEntity.java:70)
at com.foo.bar.model.BaseEntity.prePersist(BaseEntity.java:58)

我已经调试过,在Assignment实体的@PrePersist方法中,Hibernate为另一个对象调用它,即Assignment@17646,它包含Parent@17608,而parent包含具有一个元素的子级集合,即@17609。

为什么 hibernate 会尝试持久化另一个对象?

最佳答案

这些是我对您的问题的观察:

  1. 抛出的异常不是来自 Hibernate...而是来自 Hibernate由您的验证方法抛出:validateEntity(),因为您的子分配的 createDate 为 null。

  2. 您正在使用 EntityListeners 来设置 createdDatemodifiedDate 并验证您的 bean 值...但是,看起来(这是我猜测的)你的验证方法正在迭代在 hibernate 之前很久就对子分配进行(并验证)对它们执行@PrePersist!

我解决问题的建议:

  1. 使用此配置:

父级:

@OneToMany(mappedBy = "parent", CascadeType = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
private Set<Assignment> assignments;

child :

@ManyToOne
@JoinColumn(name = "parent_id")
private Parent parent;

BaseClass:将您的 prePersist 方法重命名为:

@PrePersist
@PreUpdate
public void prePersistOrUpdate() {
setCreatedDate(LocalDateTime.now());
setModifiedDate(LocalDateTime.now());
validateEntity();
}
  • 检查(并根据需要进行修改)您的基本验证方法。这方法应该只验证实例变量(如createdDate)并避免横向子对象稍后修改为 EntityListener 方法:prePersistOrUpdate() (注意,我删除了 @Valid 注释因为我不知道它的用途......可能是它被使用您的验证框架)。

  • 修改保留的业务逻辑(其中 newAssigments)像这样:

    parent.getAssignments().addAll(newAssignments);parent.getAssignments().forEach(赋值 -> assignment.setParent(parent));parentRepository.merge(父);//这应该级联并保留新的分配!

  • 关于java - Hibernate 在设置父级后尝试两次保留子级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43923530/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com