Spring/Querydsl

Querydsl - Spring Data JPA와 QueryDSL

jddng 2022. 3. 26. 21:10
728x90
반응형

 

 

Spring Data JPA와 QueryDSL

 Spring Data JPA를 사용할 때 QueryDSL을 사용하기 위해선 사용자 정의 리포지토리와 구현체를 만들어 상속받아야 한다. 

 

 

QueryDSL을 사용하기 위한 순서

 

JpaRepository를 상속받는 인터페이스 생성

 

  • Spring Data JPA에서 제공하는 JpaRepository 인터페이스를 상속받는 인터페이스 생성한다.

 

public interface MemberRepository extends JpaRepository<Member, Long> {

}

 

사용자 정의 인터페이스 생성

 

  • QueryDSL을 사용하기 위해 필요한 인터페이스 생성

 

public interface MemberRepositoryCustom {
    List<MemberTeamDto> search(MemberSearchCondition condition);	// (1)
}
  • (1) : QueryDSL로 구현할 메서드 작성

 

사용자 정의 인터페이스 구현체 생성

 

  • 사용자 정의 인터페이스의 메서드를 오버라이딩하여 QueryDSL 사용

 

@RequiredArgsConstructor
public class MemberRepositoryImpl implements MemberRepositoryCustom{

    private final JPAQueryFactory queryFactory;	// (1)

    @Override
    public List<MemberTeamDto> search(MemberSearchCondition condition) {	// (2)
        return queryFactory
                .select(new QMemberTeamDto(
                        member.id,
                        member.username,
                        member.age,
                        team.id,
                        team.name))
                .from(member)
                .leftJoin(member.team, team)
                .where(
                        usernameEq(condition.getUsername()),
                        teamNameEq(condition.getTeamName()),
                        ageGoe(condition.getAgeGoe()),
                        ageLoe(condition.getAgeLoe())
                )
                .fetch();
    }

    private BooleanExpression usernameEq(String username) {
        return StringUtils.hasText(username) ? member.username.eq(username) : null;
    }

    private BooleanExpression teamNameEq(String teamName) {
        return StringUtils.hasText(teamName) ? team.name.eq(teamName) : null;
    }

    private BooleanExpression ageGoe(Integer ageGoe) {
        return ageGoe != null ? member.age.goe(ageGoe) : null;
    }

    private BooleanExpression ageLoe(Integer ageLoe) {
        return ageLoe != null ? member.age.loe(ageLoe) : null;
    }
}
  • (1) : QueryDSL을 사용하기위한 팩토리 클래스 주입
  • (2) : 인터페이스 메서드를 오버라이드하여 동적 쿼리 구현

 

Spring Data Repository에 사용자 정의 인터페이스 상속

 

public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom {

}

 

사용자 정의 리포지토리 동작 테스트

 

@Autowired
EntityManager em;

@Autowired
MemberRepository memberRepository;

@Test
@DisplayName("사용자 정의 리포지토리 테스트")
public void searchTest2() {
    Team teamA = new Team("teamA");
    Team teamB = new Team("teamB");

    em.persist(teamA);
    em.persist(teamB);

    Member member1 = new Member("member1", 10, teamA);
    Member member2 = new Member("member2", 20, teamA);
    Member member3 = new Member("member3", 30, teamB);
    Member member4 = new Member("member4", 40, teamB);

    em.persist(member1);
    em.persist(member2);
    em.persist(member3);
    em.persist(member4);

    MemberSearchCondition condition = new MemberSearchCondition();
    condition.setAgeGoe(35);
    condition.setAgeLoe(40);
    condition.setTeamName("teamB");

    List<MemberTeamDto> results = memberRepository.search(condition);	// (1)

    assertThat(results).extracting("username").containsExactly("member4");

}
  • 사용자 정의 리포지토리 메서드 사용

 

728x90
반응형