объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом - PullRequest
505 голосов
/ 20 февраля 2010

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

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

Ответы [ 24 ]

679 голосов
/ 20 февраля 2010

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

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

196 голосов
/ 18 июня 2013

Я полагаю, что это может быть просто повторный ответ, но, чтобы уточнить, я получил это на карте @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's на Child решило проблему в обоих случаях. Это спасло Child и Parent.

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

@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "performancelog_id")
public PerformanceLog getPerformanceLog() {
    return performanceLog;
}
56 голосов
/ 29 ноября 2013

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

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

Хитрость заключается в том, чтобы убедиться, что ID и VERSION в указанном объекте установлены так, что Hibernate не думает, что указанный объект является новым объектом, который необходимо сохранить. Это сработало для меня.

Просмотрите все отношения в классе, который вы сохраняете, чтобы обработать связанные объекты (и связанные объекты связанных объектов) и убедитесь, что ID и VERSION установлены во всех объектах дерева объектов.

25 голосов
/ 28 июля 2013

Или, если вы хотите использовать минимальные «полномочия» (например, если вы не хотите каскадного удаления) для достижения того, что вы хотите, используйте

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

...

@Cascade({CascadeType.SAVE_UPDATE})
private Set<Child> children;
21 голосов
/ 19 ноября 2015

В моем случае это было вызвано отсутствием CascadeType на стороне @ManyToOne двунаправленных отношений. Чтобы быть более точным, у меня было CascadeType.ALL на @OneToMany стороне и не было на @ManyToOne. Добавление CascadeType.ALL к @ManyToOne решило проблему. Сторона один-ко-многим :

@OneToMany(cascade = CascadeType.ALL, mappedBy="globalConfig", orphanRemoval = true)
private Set<GlobalConfigScope>gcScopeSet;

сторона «многие-к-одному» (вызвала проблему)

@ManyToOne
@JoinColumn(name="global_config_id")
private GlobalConfig globalConfig;

Много-к-одному (исправлено добавлением CascadeType.PERSIST)

@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name="global_config_id")
private GlobalConfig globalConfig;
15 голосов
/ 12 марта 2014

Это произошло для меня при сохранении сущности, в которой существующая запись в базе данных имела значение NULL для поля, аннотированного @Version (для оптимистической блокировки). Обновление значения NULL до 0 в базе данных исправило это.

10 голосов
/ 21 мая 2012

Это не единственная причина ошибки. Я столкнулся с этим только что из-за ошибки опечатки в моем коде, которая, как мне кажется, установила значение сущности, которая уже была сохранена.

X x2 = new X();
x.setXid(memberid); // Error happened here - x was a previous global entity I created earlier
Y.setX(x2);

Я обнаружил ошибку, найдя, какая именно переменная вызвала ошибку (в данном случае String xid). Я использовал catch вокруг всего блока кода, который сохранил сущность и напечатал следы.

{
   code block that performed the operation
} catch (Exception e) {
   e.printStackTrace(); // put a break-point here and inspect the 'e'
   return ERROR;
}
6 голосов
/ 16 декабря 2014

Если ваша коллекция пуста, просто попробуйте: object.SetYouColection(null);

5 голосов
/ 01 июля 2016

Чтобы добавить мои 2 цента, у меня возникла такая же проблема, когда я случайно отправляю null в качестве идентификатора. Ниже приведен код моего сценария (и ОП не упомянул какой-либо конкретный сценарий) .

Employee emp = new Employee();
emp.setDept(new Dept(deptId)); // --> when deptId PKID is null, same error will be thrown
// calls to other setters...
em.persist(emp);

Здесь я устанавливаю существующий идентификатор отдела для нового экземпляра сотрудника без фактического получения объекта отдела вначале, поскольку я не хочу запускать другой запрос выбора.

В некоторых случаях deptId PKID приходит как null из вызывающего метода, и я получаю ту же ошибку.

Итак, следите за null значениями для PK ID

5 голосов
/ 15 февраля 2017

Не используйте Cascade.All, пока вам действительно не понадобится. Role и Permission имеют двунаправленное отношение manyToMany. Тогда следующий код будет работать нормально

    Permission p = new Permission();
    p.setName("help");
    Permission p2 = new Permission();
    p2.setName("self_info");
    p = (Permission)crudRepository.save(p); // returned p has id filled in.
    p2 = (Permission)crudRepository.save(p2); // so does p2.
    Role role = new Role();
    role.setAvailable(true);
    role.setDescription("a test role");
    role.setRole("admin");
    List<Permission> pList = new ArrayList<Permission>();
    pList.add(p);
    pList.add(p2);
    role.setPermissions(pList);
    crudRepository.save(role);

если объект просто «новый», он выдаст ту же ошибку.

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