본문 바로가기
내가 만난 error/해결

[Error] TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing

by 피자보다 치킨 2022. 8. 22.

 

스프링부트에서 Spring Data JPA를 공부 하던 중 Repository를 테스트하는 중 아래와 같은 TransientPropertyValueException 오류가 발생했다.

 

org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : project.toyproject.domain.Product.member -> project.toyproject.domain.Member; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : project.toyproject.domain.Product.member -> project.toyproject.domain.Member

 

 

테스트코드는 다음과 같다.

    @DisplayName("전체 상품 조회")
    @Test
    void findAll() {
        Product product = createProduct();
        Product save = productJpaRepository.save(product);
        Member member = createMember();
        Product product2 = Product.createProduct("test2", "tt.jpg", "test2", 20000, member, CategoryList.BOOKS);
        productJpaRepository.save(product2);

        List<Product> all = productJpaRepository.findAll();

 

원인

구글링 결과 원인은 영속성 때문에 발생하는 오류이다.

FK로 사용되는 컬럼값이 없는 상태에서 데이터를 넣으려다 발생한 에러이다.

나의 코드 경우 Member 데이터를 넣지않고 Product 데이터를 넣으려고 하면 Member_id값이 없기 때문에 발생하는 에러이다.

 


해결

연관 관계를 매핑할 때 사용하는  @ManyToOne, @OneToOne, @OneToMany 어노테이션에 cascade를 설정해주면 된다.

 

join 하는 쪽에 아래 코드와 같이 설정해주었다.

 

    @ManyToOne(fetch = LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "member_id")
    private Member member; //fk

 

 

CascadeType의 종류에는 다음과 같은 것들이 있다.

  • CascadeType.RESIST – 엔티티를 생성하고, 연관 엔티티를 추가하였을 때 persist() 를 수행하면 연관 엔티티도 함께 persist()가 수행된다.  만약 연관 엔티티가 DB에 등록된 키값을 가지고 있다면 detached entity passed to persist Exception이 발생한다.
  • CascadeType.MERGE – 트랜잭션이 종료되고 detach 상태에서 연관 엔티티를 추가하거나 변경된 이후에 부모 엔티티가 merge()를 수행하게 되면 변경사항이 적용된다.(연관 엔티티의 추가 및 수정 모두 반영됨)
  • CascadeType.REMOVE – 삭제 시 연관된 엔티티도 같이 삭제됨
  • CascadeType.DETACH – 부모 엔티티가 detach()를 수행하게 되면, 연관된 엔티티도 detach() 상태가 되어 변경사항이 반영되지 않는다.
  • CascadeType.ALL – 모든 Cascade 적용

 


CascadeType.ALL 주의

예전에 한 번 CascadeType.ALL로 인해 PersistentObjectException: detached entity passed to persist라는 에러를 겪은 기억이 있다.

JPA에서 자동으로 생성되는 값을 가진 필드에 직접적으로 값을 넣어 저장하고자 할 때 발생한다.

CascadeType.ALL로 개발하다 다시 저 오류가 발생하게 되면 다시 정리해야겠다.

댓글