Как заставить Hibernate удалить сирот перед обновлением
Скажем, у меня есть следующая структура модели:
@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;
}
}
В данный момент у меня есть group1
с AnnotationOption
opt1
opt2
и opt3
Затем я хочу заменить все опции только одним вариантом opt1
![введите описание изображения здесь]()
Кроме того, у меня есть ограничение в базе данных:
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.
Фактически isuue, что hibernate удаляет сирот после обновления.
Можете ли вы предложить что-то решить проблему?
Ответы
Ответ 1
В этом примере так много ошибок:
- Получение EAGER в коллекции
@OneToMany
почти всегда плохая идея.
- Однонаправленные коллекции также плохие, используйте двунаправленный.
- Если вы получаете это исключение, скорее всего, вы очистили все элементы и снова добавили те, которые хотите сохранить.
Лучший способ исправить это - явно слить существующий набор дочерних элементов с входящими, чтобы:
- Новые дочерние сущности добавляются в коллекцию.
- Удаляются дочерние объекты, которые больше не нужны.
- Дочерние объекты, соответствующие бизнес-ключу (
annotation_group_name
, study_id
), обновляются с помощью входящих данных.
Подробнее см. Высокая производительность Java Persistence.
Ответ 2
В соответствии с Hibernate documentation hibernate выполняется в следующем порядке, чтобы сохранить ограничение внешнего ключа:
- Вставляет, в порядке их выполнения.
- Обновления
- Удаление элементов коллекции
- Вставка элементов коллекции
- Удаляет, в порядке их выполнения.
Для вашей особой необходимости вам необходимо вручную очистить транзакцию, чтобы принудительно удалить ее в базе данных.