Java

QuerydslPredicateExecutor - querydsl 조건 조회 간단히 사용하기

쮸니이 2023. 1. 18. 15:55
반응형

해당 글은 김영한 님의 querydsl을 수강하며 정리하려고 적는 포스팅입니다.

 

지금 소개하는 기능은 제약이 커서 복잡한 실무 환경에 사용하기에는 많이 부족하다.

그래도 spring data에서 제공하는 기능이므로 간단히 소개하고, 왜 부족한지 설명한다.

 

💡 인터페이스 지원 - QuerydslPredicateExecutor

 

Spring Data JPA - Reference Documentation

Example 108. Using @Transactional at query methods @Transactional(readOnly = true) public interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") v

docs.spring.io

 

QuerydslPredicateExecutor 인터페이스

public interface QuerydslPredicateExecutor<T> {
    Optional<T> findById(Predicate predicate); 
    Iterable<T> findAll(Predicate predicate); 
    long count(Predicate predicate); 
    boolean exists(Predicate predicate); 
    // … more functionality omitted.
}

 

리포지토리에 적용

  • 앞서 포스팅한 MemberRepository에 QuerydslPredicateExecutor <T>를 추가해 주었다.
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom, QuerydslPredicateExecutor<Member> {
    List<Member> findByUsername(String username);
}

 

테스트

package study.querydsl.repository;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import study.querydsl.dto.MemberSearchCondition;
import study.querydsl.dto.MemberTeamDto;
import study.querydsl.entity.Member;
import study.querydsl.entity.QMember;
import study.querydsl.entity.Team;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
@Transactional
class MemberRepositoryTest {

    @PersistenceContext
    EntityManager em;

    @Autowired
    MemberRepository memberRepository;
    
    @Test
    public void querydslPredicateExecutorTest() {
        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);

        QMember member = QMember.member;
        Iterable<Member> result = memberRepository.findAll(member.age.between(10, 40).and(member.username.eq("member1")));
        for (Member findMember : result) {
            System.out.println("findMember = " + findMember);
        }
    }
}
---------------------------------------------------------------------------------------
2023-01-18T15:23:48.108+09:00 DEBUG 14500 --- [           main] org.hibernate.SQL                        : 
    /* select
        member1 
    from
        Member member1 
    where
        member1.age between ?1 and ?2 
        and member1.username = ?3 */ select
            m1_0.member_id,
            m1_0.age,
            m1_0.team_id,
            m1_0.username 
        from
            member m1_0 
        where
            m1_0.age between ? and ? 
            and m1_0.username=?
findMember = Member(id=1, username=member1, age=10)

 

한계점

  • 간단한 곳에서 사용하는 것은 가능하다.
  • 조인이 불가능 하다. (묵시적 조인은 가능하지만 left join이 불가능하다.)
  • 클라이언트가 Querydsl에 의존해야 한다.
    • service와 controller 등이 Querydsl이라는 구현 기술에 의존해야 하므로 좋지 않다.
    • repository를 만드는 이유는 하부에 querydsl과 같은 구체화된 기술을 숨기는 목적이다.
      • 만약에 querydsl이나 다른 기술을 변경하려고 할 때, repository만 변경하면 되는데 service와 controller가 의존하게 되면 모든 게 변경되어야 하기 때문에 좋지 않은 것이다.
      • 순수한 DTO 같은 class를 넘기는 것이 아니라 querydsl과 연관된 객체를 만들어 넘겨야 한다는 것이다.
  • 복잡한 실무환경에서 사용하기에는 한계가 명확하다.
참고: QuerydslPredicateExecutor 는 Pagable, Sort를 모두 지원하고 정상 동작한다

 


💡 참고 : Query Web 지원

 

한계점

  • 단순한 조건만 가능
  • 조건을 커스텀하는 기능이 복잡하고 명시적이지 않다.
  • 컨트롤러가 Querydsl에 의존한다.
  • 복잡한 실무환경에서 사용하기에 한계가 명확하다.
반응형