작성
·
163
·
수정됨
0
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)
[질문 내용]
컨트롤러
@RestController
@RequestMapping("/api/members")
@RequiredArgsConstructor
@Slf4j
public class PetController {
private final PetService petService;
@PostMapping("/pets")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<Long> createPet(
@RequestBody PetCreateRequestDto petCreateRequestDto,
@AuthenticationPrincipal PrincipalDetails principalDetails){
Member member = principalDetails.getMember();
Long savedId = petService.addPetToMember(petCreateRequestDto, member);
return ResponseEntity.ok(savedId);
}
}
서비스
@Service
@RequiredArgsConstructor
public class PetService {
private final PetRepository petRepository;
@Transactional
public Long addPetToMember(PetCreateRequestDto request, Member member) {
Pet pet = Pet.builder()
.nickname(request.nickname())
.gender(request.gender())
.age(request.age())
.photoUrl(request.photoUrl())
.description(request.description())
.likesCount(0)
.region(request.region())
.neighborhood(request.neighborhood())
.build();
pet.setPetOwner(member);
Pet savePet = petRepository.save(pet);
return savePet.getId();
}
}
연관관계 편의 메서드(Pet 엔티티에 있음)
public void setPetOwner(Member member){
this.member = member;
member.getPets().add(this); // 해당 코드에서 오류발생
}
해당 코드에서
failed to lazily initialize a collection of role: com.gdsc.petwalk.domain.member.entity.Member.pets: could not initialize proxy - no Session
가 발생하는 이유가 뭘까요?
제가 하고싶었던 건 member를 먼저 만들고, 1:N에서 N쪽인 pet에 member를 add해주고 save하면 될거라 생각했는데 아무리 생각해봐도 모르겠네요... Pet에서 Member는 @ManyToOne(fetch = FetchType.LAZY)입니다
답변 2
0
안녕하세요. 이민혁님
member는 트랜잭션 범위 밖에서(여기서는 컨트롤러에서) 조회했습니다. 이 경우 member는 준영속 상태가 됩니다.
이렇게 준영속 상태의 member를 인수로 전달했기 때문에 member의 기능에서는 지연 로딩이 발생하지 않습니다.
member 엔티티를 조회하는 위치를 트랜잭션이 시작하는 위치(여기서는 PetService.addPetToMember())에서 조회하시면 정상 작동하는 것을 볼 수 있을거에요.
추가로 다음 글도 읽어보시면 도움이 되실거에요.
https://www.inflearn.com/questions/158967
https://www.inflearn.com/questions/159466
감사합니다.
0
안녕하세요, 인프런 AI 인턴입니다. 이민혁님의 질문에 대하여 관련된 내용을 찾았습니다.
“failed to lazily initialize a collection of role” 오류는 JPA에서 엔티티의 지연 로딩(Lazy Loading) 관련 오류 중 하나입니다. 이 오류는 엔티티의 컬렉션 속성에 접근하려 할 때, 해당 컬렉션이 초기화되지 않았고, 더 이상 영속성 컨텍스트가 활성화되지 않은 상황(즉, 세션이 닫혀 있음)에서 요청이 이루어졌을 경우 발생합니다. 기본적으로, 엔티티 간의 관계가 지연 로딩으로 설정되어 있으면, 실제로 해당 컬렉션 데이터에 접근할 때까지 데이터 로딩을 지연합니다. 이 때, 데이터 접근이 이루어지는 시점에서 영속성 컨텍스트가 종료되어 있으면, JPA는 해당 데이터를 로딩할 수 없게 되며 위와 같은 오류를 발생시킵니다.
이민혁님의 경우, setPetOwner
메소드에서 member.getPets().add(this);
라인에서 오류가 발생하는데, 이는 member
의 pets
컬렉션에 접근하려 할 때, 이미 트랜잭션이 종료되었거나 해당 세션이 닫혀있어서 지연로딩을 수행할 수 없기 때문입니다.
해결 방안은 여러 가지가 있으나, 가장 일반적인 방법은 해당 로직을 트랜잭션 범위 내에서 실행해야 한다는 것입니다. @Transactional
어노테이션이 적용된 addPetToMember
메소드 내에서 컬렉션에 접근하는 로직을 처리해야 합니다. 현재 코드 상태처럼 보이지만, 문제가 발생하는 경우는 트랜잭션 관리 설정이 잘못되었거나, 다른 부분에서 문제가 발생할 수 있습니다.
유사 질문에 대한 답변이 있는 기존 게시글을 참고하시는 것도 도움이 될 수 있습니다:
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.