ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Querydsl - Spring Data JPA와 QueryDSL
    Spring/Querydsl 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
    반응형

    댓글

Designed by Tistory.