트랜잭션 문제중 맞닥뜨렸던 내용을 다시 찾아보지 않기 위해 기록한다...
아래는 내가 겪은 예외내용이다. TransientPropertyValueException 예외에 대한 내용이며 영속성 컨텍스트에 퐇마되지 않은 상태의 데이터를 사용하려 하니 발생하는 문제였다.
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.mentit.mento.global.authToken.entity.SocialAccessToken.user -> com.mentit.mento.domain.users.domain.entity.UsersEntity
저장이 되지 않은(transient) 엔티티를 참조하려할 때 발생하는 문제
1. Hiberante의 엔티티 관리
Hibernate는 엔티티의 상태를 관리하며, 엔티티가 Transient상태인지, Persistent상태인지, Detached상태인지 확인 합니다.
Transient 상태의 엔티티는 아직 영속성 컨텍스트에 포함되지 않았고, DB에 저장이 되지 않은 상태
Persistent 상태의 엔티티는 영속성 컨텍스트에 포함되어 있으며, 데이터베이스에 저장된 상태를 반영한 상태
2. 문제 상황의 코드
Users객체를 userRepository에 저장한 후 이를 기반으로 UserEntity.from 을 사용하여 UserEntity로 객체를 변경한 후 생성하려 했다.
문제는 savedUser가 Hibernate의 영속성 컨텍스트에 완전히 반영되기 전에 SocialAccessToken이 생성 및 저장되면서 해당 예외가 발생한것
3. 에러에 대한 본질
Hibernate는 데이터 무결성을 보장하기 위해, SocialAccessToken.user가 데이터베이스에 저장된 상태인지 확인한다.
하지만 UserEntity.from으로 생성된 객체는 아직 데이터베이스에 저장되지 않은 Transient상태로 간주되기 때문에 예외를 발생시킨다.
Users users = mappedUser;
userRepository.save(users);
socialAccessTokenRepository.save(SocialAccessToken.of(socialAccessToken, UsersEntity.from(mappedUser)));
isNewUser.set(true);
return users;
수정 후 코드
mappedUser 변수를 재사용하였고, 저장된 mappedUser를 사용하여 도메인에서 엔티티로 변환하였다.
그 이후 사용하니 영속성관리 내에서 이루어져 잘 해결이 되었다.
mappedUser = userRepository.save(mappedUser);
UsersEntity savedEntity = UsersEntity.from(mappedUser);
socialAccessTokenRepository.save(SocialAccessToken.of(socialAccessToken, savedEntity));
isNewUser.set(true);
return mappedUser;
'Spring > JPA' 카테고리의 다른 글
[개념 정리]Spring Boot에서 JPA의 Soft Delete와 Cascade 연관관계 (1) | 2024.12.09 |
---|---|
@Where Deprecated되고 새로 쓰이는 @SQLRestriction (1) | 2024.11.20 |
JPA - DB 연결 예외 : 'url' attribute is not specified and no embedded datasource could be configured. (0) | 2024.06.14 |
JPA - 지연로딩과 즉시로딩 (1) | 2023.12.10 |
JPA - Proxy (2) | 2023.12.10 |