Как исправить ошибку Hibernate "объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом"
У меня возникает следующая ошибка при сохранении объекта с использованием Hibernate:
object references an unsaved transient instance - save the transient instance before flushing
Как можно решить эту проблему?
5 ответ(ов)
Вы должны включить cascade="all"
(если используете XML) или cascade=CascadeType.ALL
(если используете аннотации) в вашем отображении коллекции.
Эта ошибка возникает потому, что в вашей сущности есть коллекция, и в этой коллекции есть один или несколько элементов, которые отсутствуют в базе данных. Указывая указанные выше параметры, вы сообщаете Hibernate о необходимости сохранить эти элементы в базе данных при сохранении их родителя.
Я думаю, что это, возможно, повторный ответ, но просто чтобы прояснить: я столкнулся с этой проблемой как при маппинге @OneToOne
, так и при @OneToMany
. В обоих случаях дело было в том, что объект Child
, который я добавлял к Parent
, еще не был сохранен в базе данных. Поэтому, когда я добавлял Child
к Parent
и затем сохранял Parent
, Hibernate выдавал сообщение "object references an unsaved transient instance - save the transient instance before flushing"
при сохранении Parent
.
Добавление cascade = CascadeType.ALL
в ссылке Parent
на Child
решило проблему в обоих случаях. Это сохраняло как Child
, так и Parent
.
Извините за любые повторяющиеся ответы, просто хотел прояснить для всех.
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "performancelog_id")
public PerformanceLog getPerformanceLog() {
return performanceLog;
}
Это происходит, когда Hibernate считает, что нужно сохранить объект, связанный с тем, который вы сохраняете.
У меня была такая проблема, и я не хотел сохранять изменения в связанном объекте, поэтому я установил тип каскадирования на NONE.
Секрет в том, чтобы убедиться, что ID и VERSION в связанном объекте установлены, чтобы Hibernate не воспринимал его как новый объект, который необходимо сохранить. Это мне помогло.
Просмотрите все отношения в классе, который вы сохраняете, чтобы определить связанные объекты (и связанные объекты этих связанных объектов), и убедитесь, что ID и VERSION установлены для всех объектов в дереве объектов.
Если вы хотите использовать минимально необходимые "права" (например, если вам не нужно каскадное удаление), вы можете сделать следующее:
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
...
@Cascade({CascadeType.SAVE_UPDATE})
private Set<Child> children;
В этом примере использование аннотации @Cascade
с параметром CascadeType.SAVE_UPDATE
позволит вам сохранить и обновлять объекты детей при работе с родительским объектом, не включая каскадное удаление. Это может быть полезно, если вам нужно контролировать жизненный цикл дочерних сущностей отдельно от родительской.
В моем случае проблема заключалась в том, что я не указал CascadeType
на стороне @ManyToOne
в двунаправленной связи. Если быть точным, у меня был CascadeType.ALL
на стороне @OneToMany
, но его не было на стороне @ManyToOne
. Добавление CascadeType.ALL
на стороне @ManyToOne
решило проблему.
Сторона один-ко-многим:
@OneToMany(cascade = CascadeType.ALL, mappedBy="globalConfig", orphanRemoval = true)
private Set<GlobalConfigScope> gcScopeSet;
Сторонаmany-ко-одному (причинившая проблему):
@ManyToOne
@JoinColumn(name="global_config_id")
private GlobalConfig globalConfig;
Сторона many-ко-одному (исправлено добавлением CascadeType.PERSIST
):
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name="global_config_id")
private GlobalConfig globalConfig;
Возможные значения конфигурации hbm2ddl.auto в Hibernate и их назначение
Как работают сервлеты? Инстанцирование, сессии, общие переменные и многопоточность
Разница между StringBuilder и StringBuffer
Java 8: Преобразование List<V> в Map<K, V>
Что такое PECS (Producer Extends Consumer Super)?