본문 바로가기
🔓 영구 노트

org.hibernate.TransientPropertyValueException

by 파랭이가 룰루랄라 2022. 5. 23.

기존 프로젝트에 새로운 데이터베이스 테이블을 추가하고, 실제 데이터가 제대로 저장되는지 확인하는 코드를 작성한 후에 프로젝트를 실행시켜보니 다음과 같은 예외가 발생하였습니다.

org.hibernate.TransientPropertyValueException: 
object references an unsaved transient instance 
- save the transient instance before flushing

EntityManager의 persist 함수를 통해 객체를 저장하였는데 해당 객체가 저장되는 과정에서 참조하고 있는 객체가 저장되지 않아 발생한 예외였습니다. 예외를 일으킨 코드는 다음과 같습니다.

WrongQuestion wrongQuestion = WrongQuestion.builder()
                    .question(new QuestionData(question))
                    .wrongWorkbook(wrongWorkbook)
                    .choiceList(question.getChoiceList().stream()
                            .map(ChoiceData::new)
                            .collect(Collectors.toList()))
                    .build();
em.persist(wrongQuestion);

오답 문제집에 오답을 저장하는 코드인데 해당 코드를 persist를 실행할 적에 wrongWorkbook이 데이터베이스에 저장되어 있지 않아 발생한 예외였습니다.

 

해결 방법은 다음과 같이 2가지가 있습니다.

  • cascade를 설정해주어 문제가 저장될 때 문제집이 저장되게 하는 것
  • 문제집을 먼저 저장한 후에 문제를 저장하는 것
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class WrongWorkbook extends BaseTimeEntity {
    ...
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "wrongWorkbook", cascade = CascadeType.PERSIST)
    List<WrongQuestion> wrongQuestionList = new ArrayList<>();
    ...
}

위와 같이 cascade를 설정해준 후에 em.persisit(wrongWorkbook)을 하게 되면 오답 문제집에 등록되어 있던 wrongQuestion들이 모두 저장되게 됩니다.

 

두 번째 방법은 코드는 다음과 같습니다.

...
em.persist(wrongWorkbook)
...
em.persist(wrongQuestion);

위와 같이 오답 문제의 문제집을 wrongWorkbook으로 설정하여 저장하기 전에 미리 wrongWorkbook을 저장하게 되면 예외가 발생하지 않습니다.

댓글