[JPA] 에러 could not initialize proxy - no Session(Transacional과 Lazy, 영속성 컨텍스트)

원모어깨찰빵·2024년 2월 11일

문제 상황

이전의 포스팅에서 진행한 user엔티티와 inventory엔티티의 1대1대응 관계에서 아래와 같은 오류가 발생했다.

User에 연결된 Inventory객체를 불러올 때 문제가 생긴 것인데, 현재 User은 Inventory와 단방향, fetch Lazy로 설정되어있다.

@OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_inventory_id", referencedColumnName = "inventory_id")
    private Inventory inventory;

또한 User정보를 처음 저장할때 아래와 같은 로직이 수행된다.

@Transactional
    public Users saveUser(Map<String, String> googleUserInfo) {
        Users user = Users.builder()
                .email(googleUserInfo.get("email"))
                .nickname(googleUserInfo.get("name"))
                .day(0)
                .exp(0)
                .grammarScore(0)
                .subjectScore(0)
                .vocaScore(0)
                .level(0)
                .location(0)
                .inventory(new Inventory())
                .build();
        userRepository.saveAndFlush(user);
        return user;
    }

이후, 오류가 난 로직은 아래의 코드들이다.

@Transactional(readOnly = true)
public InventoryInfoDto getInventoryInfoDto(User user) {
    Inventory userInventory = getInventoryByUser(user);
    System.out.println("inventoryId = " + userInventory.getId());
    return getInventoryInfoDtoByInventory(userInventory);
}
private Inventory getInventoryByUser(User user) {
    return user.getInventory();
}
private InventoryInfoDto getInventoryInfoDtoByInventory(Inventory inventory) {
    System.out.println("inventoryId = " + inventory.getId());
    return InventoryInfoDto.ToDto(inventory);
}

로직은 Controller부터 User객체를 넘겨받고, 해당 User에 연결된 Inventory를 가져온 후, Inventory의 정보를 DTO로 치환하여 return하는 구조이다.

문제 원인

트랜잭션 처리된 getInventoryInfoDto메소드가 실행되었을 때 시작한 트랜잭션과, 스프링에서 생명 주기를 함께하는 영속성 컨텍스트가 return InventoryInfoDto.ToDto(inventory);라인이 실행될 때 종료되면서 inventory가 실체가 null인 프록시 객체로 넘어갔기 때문이다.
!!그냥 inventory.getBoatA()도안됨 + fetch join해야될듯?
//작성중

profile
https://fuzzy-hose-356.notion.site/1ee34212ee2d42bdbb3c4a258a672612

0개의 댓글