如何在更新之前强制Hibernate删除孤立

问题描述 投票:3回答:2

假设我有以下模型结构:

@Entity
@Table(....)
public class AnnotationGroup{
    ...
    private List<AnnotationOption> options;


    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinColumn(name = "annotation_group_id", nullable = false)
    public List<AnnotationOption> getOptions() {
        return options;
    }
}

@Entity
@Table(...)
public class AnnotationOption {

    private Long id;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Override
    public Long getId() {
        return id;
    }
}

目前我有group1AnnotationOptions opt1 opt2opt3

然后我想用一个选项opt1替换所有选项

enter image description here

另外我在数据库中有约束:

    CONSTRAINT "UQ_ANNOTATION_OPTION_name_annotation_group_id" UNIQUE (annotation_option_name, annotation_group_id)

这一个火上浇油:

Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "UQ_ANNOTATION_OPTION_name_annotation_group_id"
  Detail: Key (name, annotation_group_id)=(opt1, 3) already exists.

实际上问题是hibernate在更新后删除了孤儿。

你能提出解决问题的建议吗?

java hibernate jpa constraints unique
2个回答
5
投票

在这个例子中有很多错误:

  1. 获取@OneToManycollection的EAGER是almost always a bad idea
  2. 单向收集也很糟糕,使用bidirectional one
  3. 如果您收到此异常,则很可能清除了所有元素并重新添加了要保留的元素。

解决此问题的最佳方法是将现有的子集与传入的子集明确合并,以便:

  1. 新的子实体正被添加到集合中。
  2. 将删除不再需要的子实体。
  3. 匹配业务键(annotation_group_namestudy_id)的子实体将使用传入数据进行更新。

有关更多详细信息,请查看High-Performance Java Persistence


1
投票

根据Hibernate documentation hibernate按以下顺序执行以保留外键约束:

  1. 按插入顺序执行插入
  2. 更新
  3. 删除集合元素
  4. 插入集合元素
  5. 按照执行顺序删除

为了您的特殊需要,您应该手动刷新事务以强制在数据库中删除。

© www.soinside.com 2019 - 2024. All rights reserved.