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

gst*_*low 3 java hibernate jpa constraints unique

假设我有以下模型结构:

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)
@Entity
@Table(...)
public class AnnotationOption {

    private Long id;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Override
    public Long getId() {
        return id;
    }
}
Run Code Online (Sandbox Code Playgroud)

目前,我有group1AnnotationOption小号opt1 opt2opt3

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

在此输入图像描述

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

    CONSTRAINT "UQ_ANNOTATION_OPTION_name_annotation_group_id" UNIQUE (annotation_option_name, annotation_group_id)
Run Code Online (Sandbox Code Playgroud)

这一个火上浇油:

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.
Run Code Online (Sandbox Code Playgroud)

实际上,假设hibernate在更新后删除了孤儿.

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

Vla*_*cea 5

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

  1. 获取@OneToMany集合的EAGER 几乎总是一个坏主意.
  2. 单向集合也很糟糕,使用双向集合.
  3. 如果您收到此异常,则很可能清除了所有元素并重新添加了要保留的元素.

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

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

有关更多详细信息,请查看高性能Java持久性.


Bap*_*ais 1

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

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

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