Сопоставление OneToOne приводит к тому, что родитель сохраняется дважды

#java #spring-boot #hibernate #jpa

#Ява #пружинный ботинок #зимовать #jpa

Вопрос:

В моем проекте Spring Boot Hibernate (5.5.7.Final) у меня есть родительский объект с одним единственным отношением к дочернему объекту и двумя бизнес-идентификаторами:

 @Id private long id;  @OneToOne(mappedBy = "parent", cascade = CascadeType.ALL,  fetch = FetchType.EAGER, optional = false) Child child;  @Column String idA; @Column String idB;  

У ребенка есть следующее сопоставление с родителем:

 @OneToOne @MapsId private Parent parent  

В базе данных имеется уникальный индекс МАР и ибР.

При запуске этого я вижу много повторяющихся ошибок ввода в моей базе данных, в уникальном индексе. По какой-то причине hibernate пытается вставить Parent дважды. Это каким-то образом вызвано ребенком, потому что, когда я заменяю отображение JPA на Child an @Transient , проблема исчезает.

Что может быть причиной этого?

Комментарии:

1. У вас включено изменение порядка запросов/обновлений? Какую версию Hibernate вы используете? Как вы спасаете родителя и ребенка? Можете ли вы опубликовать SQL-запросы, которые создает Hibernate, для одного сохранения, где это происходит? Это может дать представление о том, что пытается сделать Hibernate, особенно если вы также опубликуете параметры для этих запросов.

2. Спящий режим 5.5.7.Окончательный класс, который я здесь назвал родительским, на самом деле находится в каскаде. ВСЕ @OneToMany с другим классом, и мы вызываем хранилище данных Spring .save() для этого класса. Что касается переупорядочения запросов, то оно не задано, мы используем все, что указано по умолчанию. Я посмотрю насчет запросов, но это происходит не всегда, так что их может быть трудно уловить. Это также производственная система, поэтому я не могу публиковать какие-либо реальные запросы или значения

3. @JessevanBekkum, попробуйте удалить @OneToOne сопоставление из дочерней сущности

4. Если это не происходит постоянно, вам следует следить за закономерностями того, когда это происходит, например, в определенном процессе или, возможно, в комбинации действий. Затем попробуйте воспроизвести его в среде разработки или тестирования. Если вы можете получать запросы только из рабочей среды, попробуйте запутать значения — важны идентификаторы, параметры условий и параметры версии (если вы их используете). Также обратите внимание, что idA и idB может дублироваться 2 различными родительскими сущностями, поэтому фактическая проблема может быть не связана с гибернацией или, по крайней мере, связана только частично.

5. Я более или менее отладил его. Мы сохраняли дважды, и spring выполнял вставку оба раза, что вызывало эту проблему. Заменив первый на saveAndFlush, он правильно сделал вставку в первый раз и обновление во второй раз. Каким-то образом, если дочерний элемент @Transient, hibernate выполняет не вставку при втором вызове, а обновление. Я не могу объяснить эту часть