작업하면서 배우는 것들

QueryDsl 과 커스텀 리포지토리를 이용한 쿼리문 사용

Jungsoomin :) 2020. 12. 27. 12:19

실무에서는 커스텀 리포지토리를 구축하고나서 QueryDsl 을 사용한다는 이야기를 접했다.

 

조금이나마 흉내라도 내보고, 한자라도 쳐보기위해서 했던 작업을 기록한다.

 

 

첫번째로는 재정의할 메서드를 놓은 인터페이스를 정의한다.

public interface PostCustomRepository<T> {

    List<Post> findMyPost();
}

 

두번째로는 인터페이스의 구현체를 만든다. @EnableJpaRepository 에 속성에 suffix 를 바꾸는 속성이 있으니 참고한다.

QueryFactory 를 이용해서 원하는 쿼리문을 직관적으로 짜낸다.

@Repository
@Transactional
public class PostCustomRepositoryImpl implements PostCustomRepository<Post> {

    @Autowired
    EntityManager entityManager;


    @Override
    public List<Post> findMyPost() {
        JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);

        return queryFactory.select(post).from(post).where(post.id.gt(0)).fetch();

    }
}

 

사용할 리포지토리는 두개의 인터페이스를 상속하는데 JpaRepository + CustomRepository 이다. 구현체는 각각 있어 등록됬으니 괜찮다.

public interface PostRepository extends JpaRepository<Post,Long>, PostCustomRepository<Post>, QuerydslPredicateExecutor<Post> {
}

 

 

이대로 테스트 코드를 쏘면 쿼리문이 잘나온다.

 

@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
class PostRepositoryTest {

    @Autowired
    private PostRepository postRepository;

    @Test
    public void crud(){

        postRepository.findMyPost();

    };

}

 


 

심화과정, Pageable 과 같이 사용하기

 

일단 매개 값으로 Pageable 이 추가된다.

public interface PostCustomRepository<T> {
    /**
     *  
     * @return 0 보다 큰 포스트를 가져옴
     */
    Page<Post> findMyPost(Pageable pageable);
}

 

이것을 정의하는데 OrderSpecifier 를 가져오는 메서드는 static 하므로 util 로 따로 지정해서 사용하는 것이 좋다고 한다.

  • offset, limit 로 pageable 에 필요한 값을 가져오고 있음.
  • orderBy 메서드에 OrderSpecifier 를 리턴하는 메서드를 정의해서 사용 중
  • PageIml 을 사용하여 페이지 구성에 알맞은 결과를 리턴해 준다.
@Repository
@Transactional
public class PostCustomRepositoryImpl implements PostCustomRepository<Post> {

    @Autowired
    EntityManager entityManager;


    @Override
    public Page<Post> findMyPost(Pageable pageable) {
        JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);

        QueryResults<Post> postQueryResults = queryFactory.select(post).from(post).where(post.id.gt(0))
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .orderBy(getSortColumn(Order.DESC,post,"registerDate"))
                .fetchResults();
        return new PageImpl<>(postQueryResults.getResults(),pageable,postQueryResults.getTotal());
    }

    private static OrderSpecifier<?> getSortColumn(Order order, Path<?> parent, String fieldName){
        Path<Object> fieldPath = Expressions.path(Object.class,parent,fieldName);
        return new OrderSpecifier(order,fieldPath);
    }
}

 

이후 테스트 코드를 고쳐보면 이러하다.

@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
class PostRepositoryTest {

    @Autowired
    private PostRepository postRepository;

    @Test
    public void crud(){
        PageRequest request = PageRequest.of(0,10, Sort.by(Sort.Direction.DESC,"registerDate"));

        postRepository.findMyPost(request);
    };

}

참조: Stack OverFlow