'2025/05/01'에 해당되는 글 1건

728x90

QueryDSL TodoSearch 에 대한 예제다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public interface TodoRepository extends JpaRepository<Todo, Long>, TodoSearch {
}
 
// TodoSearch는 JpaRepository에 붙이면 안 되는 인터페이스 => TodoSearch는 커스텀 구현용 인터페이스
public interface TodoSearch {
    Page<Todo> search1(PageRequestDTO pageRequestDTO);
}
 
@Service
@Transactional
@Log4j2
@RequiredArgsConstructor // 생성자 자동 주입
public class TodoSearchImpl implements TodoSearch {
    // TodoSearchImpl의 이름이 정확히 TodoSearch + Impl이면,
    // Spring Data JPA는 자동으로 이를 Repository 구현으로 인식한다.
 
    private final JPAQueryFactory queryFactory;
 
    @Override
    public Page<Todo> search1(PageRequestDTO pageRequestDTO) {
        QTodo qTodo = QTodo.todo;
 
        BooleanBuilder builder = new BooleanBuilder();
 
        String keyword = pageRequestDTO.getKeyword();
        String where = pageRequestDTO.getWhere();
 
        // 검색 조건 적용
        if (keyword != null && !keyword.trim().isEmpty()) {
            switch (where) {
                case "title":
                    builder.and(qTodo.title.containsIgnoreCase(keyword));
                    break;
                case "writer":
                    builder.and(qTodo.writer.containsIgnoreCase(keyword));
                    break;
                default:
                    builder.and(
                            qTodo.title.containsIgnoreCase(keyword)
                                    .or(qTodo.writer.containsIgnoreCase(keyword))
                    );
            }
        }
 
        Pageable pageable = PageRequest.of(
                pageRequestDTO.getPage() - 1,
                pageRequestDTO.getSize(),
                Sort.by("tno").descending()
        );
 
        JPAQuery<Todo> query = queryFactory
                .selectFrom(qTodo)
                .where(builder)
                .offset(pageable.getOffset())
                .limit(pageable.getPageSize())
                .orderBy(qTodo.tno.desc());
 
        List<Todo> resultList = query.fetch();
 
        long totalCount = queryFactory
                .select(qTodo.count())
                .from(qTodo)
                .where(builder)
                .fetchOne();
 
        return new PageImpl<>(resultList, pageable, totalCount);
    }
}
 

 

QueryDSL로 직접 selectFrom(qTodo)를 사용하는 경우, 기본 정렬이 적용되지 않으며, 
Sort.by("tno").descending()과 같은 JPA Pageable의 정렬 정보도 자동 적용되지 않는다.

 

JPAQuery<Todo> query = queryFactory
    .selectFrom(qTodo)
    .where(builder)
    .offset(pageable.getOffset())
    .limit(pageable.getPageSize())
    .orderBy(qTodo.tno.desc()); 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
 
@Data
@SuperBuilder  // - **상속 관계가 있는 클래스**에서 부모 클래스의 빌더 패턴을 지원하기 위해 사용된다.
@AllArgsConstructor  // 모든 필드에 대해 값을 받아 전체 매개변수 생성자를 자동으로 생성한다.
@NoArgsConstructor
public class PageRequestDTO {
 
    @Builder.Default  // 값을 명시적으로 설정하지 않을 때만 기본값을 부여
    private int page = 1;
 
    @Builder.Default
    private int size = 10;
 
    private Integer blockSize;  // Integer로 변경 (null 체크 가능하게)
 
    private String where; // 검색 KEY 추가
    private String keyword; // 검색어
 
    public int getBlockSize() {
        // blockSize가 null이면 size와 동일하게 처리
        return (blockSize != null) ? blockSize : size;
    }
}
 

 

 

728x90
블로그 이미지

Link2Me

,