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



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



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

23 ответов:

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

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

я считаю, что это может быть просто повторный ответ, но просто чтобы уточнить, я получил это на @OneToOne отображение, а также @OneToMany. В обоих случаях дело было в том, что Child объект, который я добавлял к Parent еще не был сохранен в базе данных. Поэтому, когда я добавил Child до Parent, потом спас Parent, спящий будет бросать "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;
}

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

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

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

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

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

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

...

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

в моем случае это было вызвано отсутствием CascadeType на @ManyToOne сторона двунаправленного отношения. Если быть более точным, у меня было CascadeType.ALL on @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;

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

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

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

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

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

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

чтобы добавить мои 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);

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

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

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

Я получаю эту ошибку, когда я использую

getSession().save(object)

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

getSession().saveOrUpdate(object) 

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

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

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

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

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

код был что-то вроде этого пользователя.Ява модель:

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

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

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

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

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

для полноты картины: A

org.hibernate.TransientPropertyValueException 

С

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

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

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

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

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, чтобы сохранить их в базе данных при сохранении родительского объекта.

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

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

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);

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

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);

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

    @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;
        }

    }

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

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

корпус 1: Я получал это исключение, когда пытался создать родителя и сохранить эту родительскую ссылку на своего ребенка, а затем какой-то другой запрос на удаление/обновление(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;
    .
    .

}

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

.
.
reference.setRefAddDetails(null);
reference = referenceDao.create(reference);
entityManager.flush();
.
.

Comments

    Ничего не найдено.