인프런 커뮤니티 질문&답변

스물다섯컷의흑백필름님의 프로필 이미지
스물다섯컷의흑백필름

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

프록시

failed to lazily initialize a collection of role 에러질문

작성

·

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); 라인에서 오류가 발생하는데, 이는 memberpets 컬렉션에 접근하려 할 때, 이미 트랜잭션이 종료되었거나 해당 세션이 닫혀있어서 지연로딩을 수행할 수 없기 때문입니다.

해결 방안은 여러 가지가 있으나, 가장 일반적인 방법은 해당 로직을 트랜잭션 범위 내에서 실행해야 한다는 것입니다. @Transactional 어노테이션이 적용된 addPetToMember 메소드 내에서 컬렉션에 접근하는 로직을 처리해야 합니다. 현재 코드 상태처럼 보이지만, 문제가 발생하는 경우는 트랜잭션 관리 설정이 잘못되었거나, 다른 부분에서 문제가 발생할 수 있습니다.

유사 질문에 대한 답변이 있는 기존 게시글을 참고하시는 것도 도움이 될 수 있습니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.

현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏

추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

스물다섯컷의흑백필름님의 프로필 이미지
스물다섯컷의흑백필름

작성한 질문수

질문하기