it-roy-ru.com

объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом

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

object references an unsaved transient instance - save the transient instance before flushing
466
Tushar Ahirrao

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

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

635
Bozho

Я полагаю, что это может быть просто повторный ответ, но просто чтобы уточнить, я получил это на сопоставлении @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;
}
182
McDonald Noland

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

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

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

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

50
Cookalino

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

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

...

@Cascade({CascadeType.SAVE_UPDATE})
private Set<Child> children;
24
Haris Osmanagić

В моем случае это было вызвано отсутствием 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;
16
allap

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

14
dukethrash

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

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;
}
10
nanospeck

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

6
Joabe Lucena

Не используйте 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);

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

5
Tiina

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

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

4
manikanta

я получаю эту ошибку при использовании 

getSession().save(object)

но это работает без проблем, когда я использую 

getSession().saveOrUpdate(object) 
3
acpuma

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

merge(A);
B.setA(A);
persist(B);

В этом случае вы объединяете A, но забываете использовать объединенный объект A. Чтобы решить проблему, вы должны переписать код следующим образом.

A=merge(A);//difference is here
B.setA(A);
persist(B);
3
Hossein Nasr

Ради полноты: A

org.hibernate.TransientPropertyValueException 

с сообщением

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

также произойдет, когда вы попытаетесь сохранить/объединить сущность со ссылкой на другую сущность, которая оказывается отсоединенной .

1
Ralf

Если вы используете Spring Data JPA, то добавление аннотации @Transactional к вашей реализации сервиса решит проблему.

1
Anony

Еще одна возможная причина: в моем случае я пытался спасти ребенка перед тем, как сохранить родителя, на совершенно новом объекте.

Код был примерно таким в модели User.Java:

this.lastName = lastName;
this.isAdmin = isAdmin;
this.accountStatus = "Active";
this.setNewPassword(password);
this.timeJoin = new Date();
create();

Метод setNewPassword () создает запись PasswordHistory и добавляет ее в коллекцию истории в User. Поскольку оператор create () еще не был выполнен для родительского объекта, он пытался сохранить в коллекции сущность, которая еще не была создана. Все, что я должен был сделать, чтобы это исправить, это переместить вызов setNewPassword () после вызова create ().

this.lastName = lastName;
this.isAdmin = isAdmin;
this.accountStatus = "Active";
this.timeJoin = new Date();
create();
this.setNewPassword(password);
1
Jeremy Goodell

Я тоже столкнулся с такой же ситуацией. Установив следующую аннотацию над свойством, оно решает вопрос об исключении.

Исключение, с которым я столкнулся.

Exception in thread "main" Java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.model.Car_OneToMany

Чтобы преодолеть, аннотации я использовал.

    @OneToMany(cascade = {CascadeType.ALL})
    @Column(name = "ListOfCarsDrivenByDriver")
    private List<Car_OneToMany> listOfCarsBeingDriven = new ArrayList<Car_OneToMany>();

Что заставило Hibernate бросить исключение:

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

Предоставляя @OneToMany(cascade = {CascadeType.ALL}), он сообщает Hibernate сохранить их в базу данных при сохранении родительского объекта. 

1
Dulith De Costa

Есть еще одна возможность, которая может вызвать эту ошибку в спящем режиме. Вы можете установить несохраненную ссылку вашего объекта A на присоединенную сущность B и хотите сохранить объект C. Даже в этом случае вы получите вышеупомянутую ошибку.

1
Hossein Nasr

Я думаю, потому что вы пытаетесь сохранить объект, который имеет ссылку на другой объект, который еще не сохранен, и поэтому он пытается в «стороне БД» поместить ссылку на несуществующую строку

0
CrisMon_01

Случай 1: Я получал это исключение, когда пытался создать родителя и сохранить эту родительскую ссылку на его потомка, а затем какой-нибудь другой запрос DELETE/UPDATE (JPQL). Поэтому я просто сбрасываю () вновь созданную сущность после создания родителя и после создания дочернего объекта, используя ту же родительскую ссылку. Это сработало для меня.

Случай 2: 

Родительский класс

public class Reference implements Serializable {

    @Id
    @Column(precision=20, scale=0)
    private BigInteger id;

    @Temporal(TemporalType.TIMESTAMP)
    private Date modifiedOn;

    @OneToOne(mappedBy="reference")
    private ReferenceAdditionalDetails refAddDetails;
    . 
    .
    .
}

Детский класс:

public class ReferenceAdditionalDetails implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @OneToOne
    @JoinColumn(name="reference",referencedColumnName="id")
    private Reference reference;

    private String preferedSector1;
    private String preferedSector2;
    .
    .

}

В приведенном выше случае, когда родительский объект (Reference) и дочерний элемент (ReferenceAdditionalDetails) имеют отношение OneToOne, а также при попытке создать сущность Reference, а затем ее дочерний элемент (ReferenceAdditionalDetails), вы получите одно и то же исключение. Поэтому, чтобы избежать исключения, вы должны установить нулевой для дочернего класса, а затем создать родительский. (Пример кода)

.
.
reference.setRefAddDetails(null);
reference = referenceDao.create(reference);
entityManager.flush();
.
.
0
Harsh Vardhan Singh Solanki

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

Ниже простой экзамен отношения один к одному

insert into Department (name, numOfemp, Depno) values (?, ?, ?)
Hibernate: insert into Employee (SSN, dep_Depno, firstName, lastName, middleName, empno) values (?, ?, ?, ?, ?, ?)

Session session=sf.openSession();
        session.beginTransaction();
        session.save(dep);
        session.save(emp);
0
shashigura

Возможностей этой ошибки очень много, есть и другие возможности на странице добавления или редактирования. В моем случае я пытался сохранить объект AdvanceSalary. Проблема в том, что при редактировании AdvanceSalary employee.employee_id имеет значение null, поскольку при редактировании не был задан employee.employee_id. Я сделал скрытое поле и установил его. мой код работает абсолютно нормально.

    @Entity(name = "ic_advance_salary")
    @Table(name = "ic_advance_salary")
    public class AdvanceSalary extends BaseDO{

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private Integer id;

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "employee_id", nullable = false)
        private Employee employee;

        @Column(name = "employee_id", insertable=false, updatable=false)
        @NotNull(message="Please enter employee Id")
        private Long employee_id;

        @Column(name = "advance_date")
        @DateTimeFormat(pattern = "dd-MMM-yyyy")
        @NotNull(message="Please enter advance date")
        private Date advance_date;

        @Column(name = "amount")
        @NotNull(message="Please enter Paid Amount")
        private Double amount;

        @Column(name = "cheque_date")
        @DateTimeFormat(pattern = "dd-MMM-yyyy")
        private Date cheque_date;

        @Column(name = "cheque_no")
        private String cheque_no;

        @Column(name = "remarks")
        private String remarks;

        public AdvanceSalary() {
        }

        public AdvanceSalary(Integer advance_salary_id) {
            this.id = advance_salary_id;
        }

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public Employee getEmployee() {
            return employee;
        }

        public void setEmployee(Employee employee) {
            this.employee = employee;
        }


        public Long getEmployee_id() {
            return employee_id;
        }

        public void setEmployee_id(Long employee_id) {
            this.employee_id = employee_id;
        }

    }
0
Ravindra

Одной из возможных причин ошибки является отсутствие установки значения родительского объекта; например, для отношений отдела с сотрудниками вы должны написать это, чтобы исправить ошибку:

Department dept = (Department)session.load(Department.class, dept_code); // dept_code is from the jsp form which you get in the controller with @RequestParam String department
employee.setDepartment(dept);
0
pheromix

Я столкнулся с этим исключением, когда я не сохранил родительский объект, но я сохранял дочерний объект. Чтобы решить эту проблему, в одном сеансе я сохранил как дочерний, так и родительский объекты и использовал CascadeType.ALL для родительского объекта. 

0
tadtab

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

@Transactional
public someService() {
    Entity someEntity = new Entity();
    AssocaiatedEntity associatedEntity = new AssocaitedEntity();
    someEntity.setAssociatedEntity(associatedEntity);
    associatedEntity.setEntity(someEntity);

    // Performing any query was causing hibernate to attempt to persist the new entity. It would then throw an exception
    someDao.getSomething();

    entityDao.create(someEntity);
}

Чтобы исправить, я выполнил запрос перед созданием новой сущности. 

0
mad_fox