Java Hibernate在设置父项后尝试保留子项两次

Java Hibernate在设置父项后尝试保留子项两次,java,hibernate,jpa,spring-data-rest,Java,Hibernate,Jpa,Spring Data Rest,我有这样的Hibernate映射: 家长: @OneToMany(mappedBy = "parent") @Valid private Set<Assignment> assignments; @OneToMany(mappedBy = "parent", CascadeType = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}) private Set<Assignment> assignm

我有这样的Hibernate映射:

家长:

@OneToMany(mappedBy = "parent")
@Valid
private Set<Assignment> assignments;
@OneToMany(mappedBy = "parent", CascadeType = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
private Set<Assignment> assignments;
我遇到了这样的情况:父对象已经被持久化到数据库中,我得到了新的任务列表。我做了这样的事情(使用Spring数据JPA):

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

@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));
    }
}
我已经调试过,在@PrePersist赋值方法中,实体Hibernate为另一个对象调用它,它是Assignment@17646,其中包含Parent@17608,父元素包含子元素的集合,该集合包含一个元素@17609


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

以下是我对您的问题的观察:

  • 正在引发的异常不是来自Hibernate。。。它是 验证方法引发:
    validateEntity()
    ,因为 子项分配的createDate
    null

  • 您正在使用
    EntityListeners
    设置
    createdDate
    modifiedDate
    并验证您的bean值。。。然而,似乎 (这是我的猜测)您的验证方法正在迭代 (和验证)在休眠之前很久就在子任务上 对它们执行
    @PrePersist

  • 我对解决此问题的建议:

  • 使用此配置:
  • 家长:

    @OneToMany(mappedBy = "parent")
    @Valid
    private Set<Assignment> assignments;
    
    @OneToMany(mappedBy = "parent", CascadeType = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
    private Set<Assignment> assignments;
    
    基类:将
    prePersist
    方法重命名为:

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

  • 修改业务逻辑(其中,
    newassignments
    )被持久化 因此:

    parent.getAssignments().addAll(newAssignments)
    
    parent.getAssignments().forEach(assignment->assignment.setParent(parent))
    
    parentRepository.merge(parent);//这将级联并保持新的分配


  • 我认为您应该只将赋值添加到parent并持久化parent,而不需要将parent设置为assignments您会遇到什么样的异常。。。你能发布它吗?@Antoniossss,如果我不设置parent,hibernate不会自动执行此操作,并尝试使用parentId=null来持久化赋值,这是不正确的。如果我更改实体关系并在分配的父映射中添加nullable=“false”,则hibernate会尝试执行相同的操作(将父映射设置为分配),并出现相同的异常。@CarlitosWay编辑并添加了异常。您是对的-问题都在验证中。经过一些改动后,一切正常!
    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;
    
    @PrePersist
    @PreUpdate
    public void prePersistOrUpdate() {
        setCreatedDate(LocalDateTime.now());
        setModifiedDate(LocalDateTime.now());
        validateEntity();
    }