JPA 양방향 엔티티 매핑 중 다음과 같은 오류를 만났다.
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: app.todoit.domain.auth.entity.User.userInChallenge, could not initialize proxy - no Session at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:614) ~
@OneToMany(mappedBy = "user")
private List<Challenger> userInChallenge = new ArrayList<>();
public void add(Challenger challenger){
this.userInChallenge.add(challenger);
}
@Slf4j
@RequiredArgsConstructor
@Service
public class ChallengeService {
(생략)
//@Transactional
public void registerChallenge(User user, ChallengeDto.Create request) {
// 챌린지 생성
Challenge newChallenge = Challenge.builder()
.title(request.getTitle())
.content(request.getContent())
.day(Arrays.toString(request.getDay()))
.off_day(Arrays.toString(request.getOff_day()))
.start_date(request.getStart_date())
.end_date(request.getEnd_date())
.status(true)
.build();
challengeRepository.save(newChallenge);
// 챌린저 DB에 저장
Challenger leader = Challenger.builder()
.challenge(newChallenge)
.user(user)
.status(InviteStatus.ACCEPT)
.role(Role.Leader)
.startDate(request.getStart_date())
.build();
leader.setUser(user); // !!! 오류발생 !!!
user.getUserInChallenge().add(leader);
}
}
디버깅 결과 컨트롤러에서 인증이 완료된 유저를 가져오는 상황에서 오류가 발생했다.
@PostMapping("")
public void createChallenge(@RequestBody ChallengeDto.Create requestDto) {
User user = UserThreadLocal.get();
challengeService.registerChallenge(user, requestDto);
}
Unable to evaluate the expression Method threw 'org.hibernate.LazyInitializationException' exception.
@OneToMany로 매핑되어있는 필드를 세션 즉, 영속성 컨텍스트에 존재하지 않는 시점에서 불려졌기 때문에 오류가 났다.
(1) 즉시로딩으로 가져오기
-> 오류가 난 user 클래스의 @OneToMany에 즉시로딩 (fetch = FetchType.EAGER) 속성을 통해 해결할 수 있었다.
그런데 즉시로딩 사용 시 여러 문제점이 발생할 수 있다고 한다.
((추후에 내용을 덧붙일게요..))
(2) @Transactional
-> 이 방법은 나한테 적용되지 않았다.