Programming

오브젝트가 저장되지 않은 임시 인스턴스를 참조 함-플러시하기 전에 임시 인스턴스를 저장하십시오.

procodes 2020. 2. 10. 22:32
반응형

오브젝트가 저장되지 않은 임시 인스턴스를 참조 함-플러시하기 전에 임시 인스턴스를 저장하십시오.


최대 절전 모드를 사용하여 객체를 저장할 때 다음과 같은 오류가 발생합니다.

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

컬렉션 매핑에 ( cascade="all"xml을 사용하는 경우) 또는 cascade=CascadeType.ALL(주석을 사용하는 경우 ) 포함해야 합니다.

이것은 엔티티에 콜렉션이 있고 해당 콜렉션에 데이터베이스에없는 하나 이상의 항목이 있기 때문에 발생합니다. 위의 옵션을 지정하면 부모를 저장할 때 데이터베이스에 저장하도록 최대 절전 모드를 설정합니다.


나는 이것이 반복되는 대답 일 것이라고 생각하지만, 명확히하기 위해 @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;
}

이것은 Hibernate가 당신이 저장하고있는 객체와 관련된 객체를 저장해야한다고 생각할 때 객체를 저장할 때 발생합니다.

나는이 문제가 있었고 참조 된 객체의 변경 사항을 저장하고 싶지 않아서 캐스케이드 유형이 없음을 원했습니다.

요령은 Hibernate가 참조 된 오브젝트가 저장이 필요한 새로운 오브젝트라고 생각하지 않도록 참조 된 오브젝트의 ID와 VERSION이 설정되도록하는 것이다. 이것은 나를 위해 일했습니다.

저장하는 클래스의 모든 관계를 살펴보고 연관된 오브젝트 (및 연관된 오브젝트의 연관된 오브젝트)를 해결하고 오브젝트 트리의 모든 오브젝트에 ID 및 VERSION이 설정되어 있는지 확인하십시오.


또는 원하는 것을 달성하기 위해 최소한의 "파워"를 사용하려면 (예 : 계단식 삭제를 원하지 않는 경우)

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

...

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

제 경우이를 구비하지 기인 된 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;

데이터베이스의 기존 레코드에 @Version으로 주석이 달린 필드에 대해 NULL 값이있는 엔티티를 유지하는 경우 (낙관적 잠금의 경우)이 문제가 발생했습니다. 데이터베이스에서 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;
}

컬렉션이 nullable이면 다음을 시도하십시오. object.SetYouColection(null);


Cascade.All정말로 필요할 때까지 사용하지 마십시오 . RolePermission양방향이 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로 ID 로 보낼 때도 동일한 문제가 발생했습니다 . 아래 코드는 내 시나리오를 보여줍니다 (그리고 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);

여기서는 다른 선택 쿼리를 실행하고 싶지 않기 때문에 실제로 부서 엔티티를 먼저 얻지 않고 기존 부서 ID를 새 직원 인스턴스로 설정하고 있습니다.

일부 시나리오에서 deptIdPKID는 null호출 메소드에서 오는 것이며 동일한 오류가 발생합니다.

따라서 nullPK 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);

나는 또한 같은 상황에 직면했다. 속성 위에 다음 주석을 설정하면 예외 프롬프트가 해결되었습니다.

내가 직면 한 예외.

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에게 부모 객체를 저장하는 동안 그것들을 데이터베이스에 저장하도록 지시한다.


이 문제는로 표시된 메소드에서 새 엔터티와 관련 엔터티를 만든 @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);
}

수정하기 위해 새 엔터티를 만들기 전에 쿼리를 수행했습니다.


또 다른 가능한 이유 : 내 경우에는 부모를 저장하기 전에 자녀를 새로운 엔티티에 저장하려고했습니다.

코드는 User.java 모델에서 다음과 같습니다.

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

setNewPassword () 메소드는 PasswordHistory 레코드를 작성하고이를 사용자의 히스토리 콜렉션에 추가합니다. 부모에 대해 create () 문이 아직 실행되지 않았으므로 아직 생성되지 않은 엔터티 컬렉션에 저장하려고했습니다. 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

분리 될 다른 엔터티에 대한 참조로 엔터티를 유지 / 병합하려고 할 때도 발생합니다 .


아직 지속되지 않은 다른 객체에 대한 참조가있는 객체를 유지하려고했기 때문에 존재하지 않는 행에 대한 참조를 "DB 측"에서 시도하기 때문입니다.


이 문제를 해결하는 간단한 방법은 두 엔티티를 모두 저장하는 것입니다. 먼저 하위 항목을 저장 한 다음 상위 항목을 저장하십시오. 부모 엔터티는 외래 키 값의 자식 엔터티에 의존하기 때문입니다.

일대일 관계에 대한 간단한 시험 아래

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 객체를 저장하려고했습니다. 문제는 편집시 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;
        }

    }

부모 객체를 유지하지 못했지만 자식을 저장하는 경우이 예외에 직면했습니다. 이 문제를 해결하기 위해 동일한 세션에서 자식 및 부모 개체를 모두 유지하고 부모에서 CascadeType.ALL을 사용했습니다.


사례 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;
    .
    .

}

위의 경우 OneToOne 관계가있는 parent (Reference) 및 child (ReferenceAdditionalDetails)이고 Reference 엔터티를 만든 다음 해당 자식 (ReferenceAdditionalDetails)을 만들려고하면 동일한 예외가 발생합니다. 따라서 예외를 피하려면 하위 클래스에 대해 null을 설정 한 다음 상위 클래스를 작성해야합니다. (샘플 코드)

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

참고 URL : https://stackoverflow.com/questions/2302802/object-references-an-unsaved-transient-instance-save-the-transient-instance-be



반응형