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

김나영·2023년 7월 25일
1

SPRING

목록 보기
10/11
post-thumbnail

오늘도 시작된 오류타임~!
심지어 이거 전에 마주친 오류임 ㅎ~!ㅋㅋㅋㅋ!!!!!!!!!! 🖕🖕🖕🖕
그때 적어놨으면 쉽게 해결했을텐데
또 오류 기록 안해서 같은 오류도 두번 검색해서 찾아내쥬 ㅎㅎㅋ~! 내 수준 알만하고~~~

전에 상품을 등록할때 회원의번호도 함께 저장되게 하기 위해서 상품TABLE과 회원TABLE을 조인할때 마주했던 오류이다.
이번에 배송정책TABLE에 회원번호도 저장하려고 하니 뜬 오류이니... 같은 방법으로 해결하면 되것지 머....

오류메시지

org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : growto.entity.DeliveryEntity.memberEntity -> growto.entity.MemberEntity
	at org.hibernate.engine.spi.CascadingActions$8.noCascade(CascadingActions.java:379) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:169) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:159) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:149) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:82) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1407) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:489) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3303) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2438) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:449) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]

해당 오류는 @OneToMany @ManyToOne 애너테이션을 사용할 때 뜨는 오류라고 한다..
FK 영속화 문제라고도 한다..
FK가 없는 상태에서 데이터를 저장할 때 발생하는 에러!

이러한 문제를 해결하기 위해서는
영속성전이를 해주면 되는데
매핑을 위한 애너테이션들에 cascade 설정을 진행해주면 간단하게 해결 가능하다~!
cascade=CascadeType.ALL

그렇다면 CascadeType에는 어떤것들이 있을까?

CascadeType

종류설명
CascadeType.PERSIST하위 엔티티까지 영속성 전달
엔티티를 생성하고, 연관 엔티티를 추가한 상태로 영속화할 때 연관 엔티티도 함께 persist()가 수행된다.
CascadeType.MERGE하위 엔티티까지 병합 작업 지속
트랜잭션이 종료되고 detach 상태에서 연관 엔티티를 추가하거나 변경된 이후에 부모 엔티티가 merge를 수행하게 되면 변경사항이 연관 엔티티에도 적용된다.
CascadeType.REMOVE하위 엔티티까지 제거 작업 지속
엔티티를 삭제할 때 이 필드에 보유된 엔티티도 삭제한다.
CascadeType.REFRESH데이터베이스로부터 인스턴스 값을 다시 읽어옴 (새로고침)
엔티티를 새로고칠 때 이 필드에 보유된 엔티티도 새로고친다.
CascadeType.DETACH영속성 컨텍스트에서 엔티티 제거
부모 엔티티가 detach()를 수행하게 되면 연관된 엔티티도 detach()상태가 되어 변경사항이 반영되지 않는다.
CascadeType.ALL상위 엔티티에서 하위 엔티티로 모든 작업을 전파
모든 cascade를 적용시킨다.



이때 대갈쓰를 스쳐가는 한가지가,

나 로그인상태가 아니라 회원에 대한 정보를 못가져 오는구나...

그도 그럴게.. 저장할때의 controller코드에서 memberNo를 가져오는 코드는 이것이니까,,!

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String userEmail = authentication.getName();
Long memberId = (Long)memberService.getMemberIdByEmail(userEmail);



casecadeType 지정 안해주고 그냥 로그인하니까 너무 저장 잘되는거임 ^^~!
...
에혀...

DB 확인

아~~~주 잘 저장된다.. 오류 없이..
안녕하세요? 바보입니다?

profile
응애 나 애기 개발자

0개의 댓글