Light Blue Pointer
본문 바로가기
Journal

QueryDSL로 검색 기능 구현 + 쿼리 빌드 단계적으로 하기 + LocalDateTime을 Controller의 Parameter로 받을 때 주의할 점

by 개발바닥곰발바닥!!! 2024. 9. 5.

QueryDSL 설정법은 여기로

 

QueryDSL 설정

일단 gradle에 관련 설정들을 추가해준다plugins { id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'}configurations { compileOnly { extendsFrom annotationProcessor }}repositories { mavenCentral()}dependencies { implementation 'org.springfr

greedydeveloper.tistory.com

 

오늘 여러 조건에 따라서 검색을 해야하는 쿼리를 작성해야 했는데

검색할때 쿼리가 null인 경우를 모두 메서드로 분리해서 하지 않고 null이거나 비어있으면 제외하고 쿼리를 빌드하는 코드를 작성해 보았다 

 

TestCaseDslRepository

@Override
    public List<TestCase> searchTestCases(Integer page, Integer size, String author, LocalDateTime from, LocalDateTime to, String status) {
        TestCaseQueryBuilder queryBuilder = new TestCaseQueryBuilder(queryFactory);

        queryBuilder
                .withAuthor(author)
                .fromTo(from, to)
                .withResult(status)
                ;

        int offset = page * size;

        return queryBuilder.build()
                .offset(offset)
                .limit(size)
                .fetch();
    }

 

 

그리고 저번에 spatial index할 때는 JPQL을 해야 해서 못 했던 JPAQuery로 나눠서 빌드하는 클래스도 작성해보았다!

public class TestCaseQueryBuilder {

    private final JPAQuery<TestCase> query;

    public TestCaseQueryBuilder(JPAQueryFactory jpaQueryFactory) {
        this.query = jpaQueryFactory.selectFrom(testCase);
    }

    public TestCaseQueryBuilder withAuthor(String author) {
        if (author != null && !author.trim().isEmpty()) {
            this.query.where(testCase.author.eq(author));
        }
        return this;
    }

    public TestCaseQueryBuilder withResult(String result) {
        if (result != null && !result.trim().isEmpty()) {
            this.query.where(testCase.result.eq(result));
        }
        return this;
    }

    public TestCaseQueryBuilder fromTo(LocalDateTime from, LocalDateTime to) {
        if (from != null && to != null) {
            this.query.where(testCase.createdAt.between(from, to));
        } else if (from != null) {
            this.query.where(testCase.createdAt.goe(from));
        } else if (to != null) {
            this.query.where(testCase.createdAt.loe(to));
        }
        return this;
    }

    public JPAQuery<TestCase> build() {
        return query;
    }
}

TestCaseService

@Override
    public List<BriefTestCaseResponse> searchTestCases(Integer page, Integer size, String author, LocalDateTime from, LocalDateTime to, String result) {
        List<TestCase> testCases = testCaseDslRepository.searchTestCases(page, size, author, from, to, result);
        return testCases.stream().map(testCase -> modelMapper.map(testCase, BriefTestCaseResponse.class)).collect(Collectors.toList());
    }

 

TestCaseController

@GetMapping("/search")
    public ResultEntity searchTestCases(
            @RequestParam(name = "page") Integer page,
            @RequestParam(name = "size") Integer size,
            @RequestParam(name = "author") String author,
            @RequestParam(name = "from") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime from,
            @RequestParam(name = "to") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime to,
            @RequestParam(name = "status") String status
    ) {
        List<BriefTestCaseResponse> responses = verificationService.searchTestCases(page, size, author, from, to, status);
        return ResultEntity.success().message("testcase 검색 목록 조회 성공").data(responses);
    }

@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) 이걸 달아줘야 Parameter의 LocalDateTime이 잘 들어간다는 것을 알게 되었다

 

그리고 이미 있는 코드에다 저걸 적용해서 원래 하던 것처럼 JPAConfig를 따로 만들 수 없었다

 

@EnableJpaAuditing 이 한 곳에서만 정의되어야 하는 이유

습관처럼 QueryDsl을 사용하기 위해 JPAConfig를 만들려고 했다@Configuration@EnableJpaAuditingpublic class JPAConfig { @PersistenceContext private EntityManager entityManager; @Bean public JPAQueryFactory queryFactory() { return new JPAQuery

greedydeveloper.tistory.com