[JPA 오류] TransientPropertyValueException: object references an unsaved transient instance (One To One)
1. 문제 상황 및 원인
- 출금 계좌 등록 요청을 보냈을 때, memberExtra 객체가 아직 영속성 컨텍스트에 등록되지 않은 상태에서 memberExtra를 member 엔티티의 memberExtra 필드에 저장하려고 할 때 에러가 발생했다.
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.example.mutbooks.app.member.entity.Member.memberExtra -> com.example.mutbooks.app.member.entity.MemberExtra
at org.hibernate.engine.spi.CascadingActions$8.noCascade(CascadingActions.java:379) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:169) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:159) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:149) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:82) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1407) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:489) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3290) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2425) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:449) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.6.11.Final.jar:5.6.11.Final]
1) MemberService 의 createBankInfo()
// 계좌 등록
@Transactional
public void createBankInfo(Member member, WithdrawAccountForm withDrawAccountForm) {
MemberExtra memberExtra = MemberExtra.builder()
.member(member)
.bankName(withDrawAccountForm.getBankName())
.bankAccountNo(withDrawAccountForm.getBankAccountNo())
.build();
member.modifyMemberExtra(memberExtra);
// TODO: 계좌 정보는 memberContext 값에 담겨있지 않으므로 세션값 강제 수정할 필요X
//forceAuthentication(member);
}
- memberExtra 를 아직 저장하지 않은 상태에서 member.modifyMemberExtra(memberExtra)를 호출 하게 되어 문제 발생
2) MemberExtra
public class MemberExtra extends BaseEntity {
@OneToOne
private Member member; // 관련 회원
private String bankName; // 출금 은행명
private String bankAccountNo; // 출금 계좌번호
}
3) Member
public class Member extends BaseEntity {
...
@OneToOne(mappedBy = "member")
private MemberExtra memberExtra;
...
}
2. 해결 방법
부모 객체에 선언한 자식 객체에 CascadeType.ALL을 선언한다. 이를 통해 영속성 전이가 발생해 부모 객체를 저장할 때, 자식 객체도 함께 저장할 수 있다.
즉, Member 엔티티의 MemberExtra 필드 위에 CascadeType.ALL 을 추가한다.
public class Member extends BaseEntity {
...
@OneToOne(mappedBy = "member", cascade = CascadeType.ALL)
private MemberExtra memberExtra;
...
}
[ERROR] JPA TransientPropertyValueException: object references an unsaved transient instance
1. 문제 JPA를 사용해 객체간 @OneToOne 관계를 설정한뒤 Repository의 save를 호출할때 아래와 같은 에러가 발생할 수 있다. 2. 원인 이러한 상황은 주로 부모객체에서 자식객체를 한번에 저장하려고할
minholee93.tistory.com
https://velog.io/@max9106/JPA%EC%97%94%ED%8B%B0%ED%8B%B0-%EC%83%81%ED%83%9C-Cascade
[JPA]엔티티 상태 & Cascade
cascade 옵션이란 @OneToMany 나 @ManyToOne에 옵션으로 줄 수 있는 값이다.Entity의 상태 변화를 전파시키는 옵션이다.만약 Entity의 상태 변화가 있으면 연관되어 있는(ex. @OneToMany, @ManyToOne) Entity에도 상태
velog.io