JPA Querydsl Repository Support 활용

2021. 10. 6. 18:50 Spring Data/Spring Data JPA Querydsl

Spring data JPA Querydsl 기능 중에 리포지토리 지원하는QuerydslRepositorySupport을 통해 좀 더 편리한 기능을 사용하고자 합니다.

방법

1. Repository를 방식처럼 JpaRepository<EntityType, IdType>을 상속 받는 인터페이스를 만듭니다.

예시 코드

// 스프링 데이터 리포지토리에 사용자 정의 인터페이스 상속 (MemberRepositoryCustom)
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom {
    List<Member> findByUsername(String username);
}

2. MemberRepository를 만든다 (여기서는 MemberRepositoryCustom)

- 이 인터페이스는 Custom한 메서드들을 정의한다.

 

3. 2번에서 정의한 MemberRepository를 구현하는 Impl단에 MemberRepositoryImpl 클래스를 생성합니다.

그 다음 extends QuerydslRepositorySupport 클래스를 상속 받도록 합니다.

 

Tip : implements MemberRepositoryCustom 앞에 상속을 먼저 선언 해줘야 합니다.

- QuerydslRepositorySupport를 상속하게되면 더 이상 QueryDsl을 사용할 수 없습니다.

단, 생성자에서 super(EntityTpe.class)를 호출하면 가능 함.

 

예시 코드

public class MemberRepositoryImpl extends QuerydslRepositorySupport implements MemberRepositoryCustom {
    public MemberRepositoryImpl() {
        super(Member.class);
    }

//  QuerydslRepositorySupport 사용
//  from절이 먼저 시작합니다.
    private Page<MemberTeamDto> getMemberTeamDtoQueryResults(MemberSearchCondition condition, Pageable pageable){
        JPQLQuery<MemberTeamDto> jpaQuery = from(member)
                .leftJoin(member.team, team)
                .where(usernameEq(condition.getUsername()),
                        teamNameEq(condition.getTeamName()),
                        ageGoe(condition.getAgeGoe()),
                        ageLoe(condition.getAgeLoe()))
                .select(new QMemberTeamDto(
                        member.id.as("memberId"),
                        member.username,
                        member.age,
                        team.id.as("teamId"),
                        team.name.as("teamName")));

        JPQLQuery<MemberTeamDto> query = getQuerydsl().applyPagination(pageable, jpaQuery);// offset, limit 지원

        query.fetch();
    }

    @Override
    public List<MemberTeamDto> search(MemberSearchCondition condition) {
        List<MemberTeamDto> result = from(member)
                .leftJoin(member.team, team)
                .where(usernameEq(condition.getUsername()),
                        teamNameEq(condition.getTeamName()),
                        ageGoe(condition.getAgeGoe()),
                        ageLoe(condition.getAgeLoe()))
                .select(new QMemberTeamDto(
                        member.id.as("memberId"),
                        member.username,
                        member.age,
                        team.id.as("teamId"),
                        team.name.as("teamName")))
                .fetch();
    }

}

 

* MemberRepository에서 JpaRepository를 extends 했기 때문에 

  JpaRepository가 지원하는 기본 메서드들을 사용할 수 있습니다.

 

마무리로, QuerydslRepositorySupport 장단점에 대해 정리 하겠습니다.

 

* 특징 : QuerydslRepositorySupport을 상속받아서 사용 (extends QuerydslRepositorySupport)

 

* 장점 :
1. getQuerydsl().applyPagination() 스프링 데이터가 제공하는 페이징을 Querydsl로 편리하게 변환 가능(단! Sort는 오류발생)
2. from() 으로 시작 가능(최근에는 QueryFactory를 사용해서 select() 로 시작하는 것이 더 명시적)
3. EntityManager 제공
4. offset, limit 지원

 

* 한계(단점) :
1. Querydsl 3.x 버전을 대상으로 만듬
2. Querydsl 4.x에 나온 JPAQueryFactory로 시작할 수 없음
3. select로 시작할 수 없음 (from으로 시작해야함)
4. QueryFactory 를 제공하지 않음
5. 스프링 데이터 Sort 기능이 정상 동작하지 않음 -> 큐 소트를 사용하면 되긴함. (소팅을 직접해줘야 된다는 의미)
6. 메서드 체인이 끊깁니다.

 

출처 :

인프런 - 김영한의 querydsl

https://prodo-developer.tistory.com/12