인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

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

phc님의 프로필 이미지
phc

작성한 질문수

실전! Querydsl

JPA N+1 (entity 안의 entity 연결시)

작성

·

233

0

안녕하세요. 강사님.

강의 내용을 참고로 현업에서 구현중에 궁금한 점이 있어 질문들 드립니다. ^^

JPA N+1 관련 내용인데요.

@ManyToOne 이나 @OneToOne 으로 2개의 테이블을 단방향으로 연결한 후, 해당 정보를 다른 entity에서 @ManyToOne 으로 양방향 설정을 할 경우에

조회시 처음 @ManyToOne으로 연결된 부분의 데이터도 fetchJoin으로 가져올 수 있나요?

[예시]

1. Entity 정보

  1) 사용자 : UserEntity

  2) 사용자 아바타 : AvatarEntity

  3) 게시판 : BoardEntity

2. 연결정보

  1) BoardEntity.createUser = UserEntity (N:1)

  2) UserEntity.avatar = AvatarEntity (N:1 or 1:1)

3. 상태

  1) 게시판 내용 조회 시 createUser 정보를 UserEntity에서 조회 (이때 avatar 정보도 같이 fetchJoin)

  2) UserEntity와 AvatarEntity 의 fetch 를 EAGER 로 할 경우 -> 게시판내용과 사용장 정보 1회 + AvatarEntity 반복

  3) UserEntity와 AvatarEntity 의 fetch 를 LAZY 로 할 경우 -> 게시판 내용 1회 + 사용자 정보 반복 + AvatarEntity 반복

-----------------------------------

@Entity

@Table(name = "user_tab")

data class UserEntity(

    @Id @GeneratedValue(generator = "system-uuid")

    @GenericGenerator(name = "system-uuid", strategy = "uuid")

    @Column(name = "user_key", length = 128)

    var userKey: String = "",



    @Column(name = "user_id", length = 128)

    var userId: String = "",

 

 @ManyToOne(cascade = [CascadeType.ALL], optional = false, fetch = FetchType.LAZY)

    //@ManyToOne(cascade = [CascadeType.ALL], optional = false, fetch = FetchType.EAGER)

 //@OneToOne(cascade = [CascadeType.ALL], optional = false, fetch = FetchType.LAZY)

    @JoinColumn(name = "avatar_id")

    var avatar: AvatarEntity = AvatarEntity()

)



@Entity

@Table(name = "avatar_tab")

data class AvatarEntity(

    @Id

    @GeneratedValue(generator = "system-uuid")

    @GenericGenerator(name = "system-uuid", strategy = "uuid")

    @Column(name = "avatar_id", length = 128)

    var avatarId: String = "",



    @Column(name = "avatar_type", length = 100)

    var avatarType: String = UserConstants.AvatarType.FILE.code,



    @Column(name = "avatar_value", length = 512)

    var avatarValue: String = UserConstants.AVATAR_BASIC_FILE_NAME

)



@Entity

@Table(name = "board_tab")

data class BoardEntity(

    @Id @GeneratedValue(generator = "system-uuid")

    @GenericGenerator(name = "system-uuid", strategy = "uuid")

    @Column(name = "board_id")

    var boardId: String = "",

 

 @Column(name = "board_group")

    var boardGroup: String = "",



    @Column(name = "board_title")

    var boardTitle: String = "",

 

 @CreatedBy

    @JoinColumn(name = "create_user_key", nullable = false, updatable = false)

    @ManyToOne(fetch = FetchType.LAZY)

    var createUser: UserEntity? = null,

 

    ...

)



-- querydsl 조회

    override fun findBoardList(limit: Long): List<BoardEntity> {

        val board = QBoardEntity.boardEntity

        return from(board).distinct()

            .innerJoin(board.createUser).fetchJoin()

            .orderBy(board.createDt.desc())

            .limit(limit)

            .fetch()

    }

-----------------------------------

위의 경우처럼 게시판을 조회할 때 사용자 정보를 포함하여 단일 쿼리로 가져오려고 합니다.

이때, 사용자의 아바타 정보도 포함하여 가져오고 싶은데... 아바타만 반복조회로 실행됩니다.

이부분은 어떻게 처리하는지 궁금합니다.

답변 1

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. phc님^^

1. 모든 연관관계는 지연로딩으로 설정해주세요.

2. XtoOne 관계는 무한대로 패치조인이 가능합니다.

따라서 user -> avatar로 추가로 패치조인 하시면 문제가 해결됩니다.

관련해서 활용2편에서 매우 자세하게 설명드리고 있습니다. 꼭! 활용2편을 마스터주세요^^!

감사합니다.

phc님의 프로필 이미지
phc

작성한 질문수

질문하기