JPA Troubleshooting - save the transient instance before flushing

choko's avatar
Jun 29, 2024
JPA Troubleshooting - save the transient instance before flushing
 
Summary
  • 연관관계를 맺는 엔티티간의 요청에서, FK로 쓰는 객체가 아직 저장이 되지 않아 발생하는 오류이다.
  • 엔티티의 연관관계가 있을 경우에는 @Cascade 옵션을 설정해준다.
  • 연관관계의 FK로 사용할 객체는 새로 생성하지 말고 jpa query를 통해 가져와야 한다.
 
 

증상

  • User와 @OneToMany 관계인 Authority를 추가하려고 할 때, authority.setUser(user) 부분에서 에러 발생
@Test void jpaTest2() { USERTest user = new USERTest(); user.setUsername("test0"); List<AUTHORITYTEST> authorityList = authorityTestRepository.findAuthorityByUserName(user.getUsername()); AUTHORITYTEST authority = new AUTHORITYTEST(); authority.setUser(user); // error ! authority.setUserName(user.getUsername()); authority.setAuthority("ROLE_ADMIN"); authorityTestRepository.save(authority); }
 
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : tom.study.domain.test.AUTHORITYTEST.user -> tom.study.domain.test.USERTest
 
 

원인

  • 연관관계를 맺는 엔티티간의 요청에서, FK로 쓰는 객체가 아직 저장이 되지 않아 발생하는 오류.
 

해결법

  • 위 코드에서, User를 새로 만들어서 authority.setUser(user);로 하는 부분이 잘못되었다.
  • User를 새로 만드는게 아닌, Jpa 쿼리를 통해 가져와서 setUser에 넣어주면, 저장이 되어있는 객체이기 때문에 에러가 발생하지 않는다.
void jpaTest2() { USERTest user = userTestRepository.findByUserName("test0").orElseThrow(); List<AUTHORITYTEST> authorityList = authorityTestRepository.findAuthorityByUserName(user.getUsername()); AUTHORITYTEST authority = new AUTHORITYTEST(); authority.setUser(user); authority.setUserName(user.getUsername()); authority.setAuthority("ROLE_ADMIN"); authorityTestRepository.save(authority); }
 
 
Share article

Tom의 TIL 정리방