Вопрос-ответ

How to fix the Hibernate "object references an unsaved transient instance - save the transient instance before flushing" error

Как исправить ошибку Hibernate "объект ссылается на несохраненный переходный экземпляр - сохраните переходный экземпляр перед сбросом"

При сохранении объекта с помощью Hibernate я получаю следующую ошибку

object references an unsaved transient instance - save the transient instance before flushing
Переведено автоматически
Ответ 1

Вы должны включить cascade="all" (если используете xml) или cascade=CascadeType.ALL (если используете аннотации) в сопоставление вашей коллекции.

Это происходит потому, что у вас есть коллекция в вашей сущности, и в этой коллекции есть один или несколько элементов, которых нет в базе данных. Указав вышеуказанные параметры, вы указываете hibernate сохранить их в базе данных при сохранении их родительского элемента.

Ответ 2

Я полагаю, что это может быть просто повторным ответом, но просто для пояснения, я получил это на @OneToOne сопоставлении, а также на @OneToMany. В обоих случаях это был тот факт, что Child объект, который я добавлял в Parent, еще не был сохранен в базе данных. Итак, когда я добавил Child в Parent, а затем сохранил Parent, Hibernate выдавал "object references an unsaved transient instance - save the transient instance before flushing" сообщение при сохранении родительского объекта.

Добавление в cascade = CascadeType.ALL на Parent's ссылку на Child решило проблему в обоих случаях. Это спасло Child и Parent.

Извините за повторяющиеся ответы, просто хотел уточнить для людей.

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "performancelog_id")
public PerformanceLog getPerformanceLog() {
return performanceLog;
}
Ответ 3

Введение

При использовании JPA и Hibernate объект может находиться в одном из следующих 4 состояний:


  • Новый - Недавно созданный объект, который никогда не был связан с сеансом гибернации (он же Контекст сохранения) и не сопоставлен ни с одной строкой таблицы базы данных, считается находящимся в Новом или переходном состоянии.

Для сохранения нам нужно либо явно вызвать метод persist, либо использовать механизм переходного сохранения.


  • Постоянный - постоянный объект был связан со строкой таблицы базы данных, и он управляется текущим контекстом сохранения.

Любое изменение, внесенное в такой объект, будет обнаружено и передано в базу данных (во время сброса сеанса).


  • Отсоединен - После закрытия текущего контекста сохранения все ранее управляемые объекты отсоединяются. Последовательные изменения больше не будут отслеживаться, и автоматическая синхронизация базы данных не произойдет.



  • Удалено - Хотя JPA требует, чтобы разрешалось удалять только управляемые объекты, Hibernate также может удалять отдельные объекты (но только через remove вызов метода).



Переходы состояний объектов

Чтобы переместить объект из одного состояния в другое, вы можете использовать методы persist, remove или merge.

Состояния объекта JPA

Исправляем проблему

Проблема, которую вы описываете в своем вопросе:

object references an unsaved transient instance - save the transient instance before flushing

вызвано связыванием объекта в состоянии New с объектом, который находится в состоянии Managed.

Это может произойти, когда вы связываете дочерний объект с коллекцией "один ко многим" в родительском объекте, и коллекция не cascade выполняет переходы состояния объекта.

Итак, вы можете исправить это, добавив cascade к ассоциации объектов, которая вызвала этот сбой, следующим образом:

@OneToOne Ассоциация

@OneToOne(
mappedBy = "post",
orphanRemoval = true,
cascade = CascadeType.ALL)

private PostDetails details;

Обратите внимание на CascadeType.ALL значение, которое мы добавили для cascade атрибута.


@OneToMany Ассоциация

@OneToMany(
mappedBy = "post",
orphanRemoval = true,
cascade = CascadeType.ALL)

private List<Comment> comments = new ArrayList<>();

Опять же, CascadeType.ALL подходит для двунаправленных @OneToMany ассоциаций.

Теперь, чтобы каскад работал должным образом в двунаправленном режиме, вам также необходимо убедиться, что родительская и дочерняя ассоциации синхронизированы.

@ManyToMany Ассоциация

@ManyToMany(
mappedBy = "authors",
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
}
)

private List<Book> books = new ArrayList<>();

В @ManyToMany ассоциации вы не можете использовать CascadeType.ALL or orphanRemoval, поскольку это приведет к распространению перехода состояния объекта удаления от одного родительского объекта к другому родительскому объекту.

Поэтому для @ManyToMany ассоциаций вы обычно выполняете каскадные операции CascadeType.PERSIST или CascadeType.MERGE. В качестве альтернативы вы можете расширить это значение до DETACH или REFRESH.

Ответ 4

Это происходит при сохранении объекта, когда Hibernate считает, что ему нужно сохранить объект, связанный с тем, который вы сохраняете.

У меня была эта проблема, и я не хотел сохранять изменения в указанном объекте, поэтому я хотел, чтобы каскадный тип был NONE.

Хитрость заключается в том, чтобы убедиться, что идентификатор и ВЕРСИЯ в объекте, на который ссылается объект, установлены таким образом, чтобы Hibernate не думал, что объект, на который ссылается, является новым объектом, который нуждается в сохранении. У меня это сработало.

Просмотрите все отношения в классе, который вы сохраняете, чтобы определить связанные объекты (и связанные объекты связанных объектов) и убедитесь, что идентификатор и ВЕРСИЯ установлены во всех объектах дерева объектов.

java hibernate jpa