좋아요! 지금 작성한 코드는 QueryDSL을 활용한 동적 쿼리 예제예요. 각 부분을 천천히, 아주 자세하게 설명드릴게요. 😌
이 코드는 사용자의 검색 조건(searchCondition) 과 검색어(searchKeyword) 에 따라 조건문을 동적으로 생성하고, 해당 조건에 맞는 Board 엔티티들을 페이징하여 조회하는 동적 쿼리 테스트입니다.
DynamicBoardRepositorypublic interface DynamicBoardRepository extends JpaRepository<Board, Long>, QuerydslPredicateExecutor<Board>
JpaRepository<Board, Long>
→ 일반적인 CRUD 메소드들 사용 가능 (save, findById 등)
QuerydslPredicateExecutor<Board>
→ BooleanBuilder 같은 QueryDSL 조건을 기반으로 동적 쿼리를 실행할 수 있게 함
→ 즉, findAll(Predicate, Pageable) 같은 메소드 사용 가능
@Test 메소드 전체 설명@Test
public void testDynamicQuery() {
테스트 실행용 메소드입니다.
String searchCondition = "TITLE";사용자가 제목으로 검색할지, 내용으로 검색할지를 의미합니다.
예: "TITLE" 혹은 "CONTENT" 등
String searchKeyword = "title10";검색어를 의미합니다. 지금은 "title10"을 기준으로 검색합니다.
BooleanBuilder builder = new BooleanBuilder();이게 핵심입니다. QueryDSL에서 제공하는 조건 조합 객체입니다.
.and(), .or() 등으로 연결해서 쿼리 조건을 동적으로 누적할 수 있어요.WHERE 절을 동적으로 만들 수 있게 해주는 빌더입니다.QBoard qboard = QBoard.board;이것도 매우 중요해요.
QBoard는 Board 엔티티로부터 QueryDSL이 자동으로 생성한 클래스입니다.QBoard.board.title → Board 엔티티의 title 필드에 해당QBoard.board.content → Board의 content 필드즉, 이 객체를 통해 타입 안정성 있게 엔티티의 필드에 접근할 수 있어요.
if (searchCondition.equals("TITLE")) {
builder.and(qboard.title.contains(searchKeyword));
} else if (searchCondition.equals("CONTENT")) {
builder.and(qboard.content.like("%" + searchKeyword + "%"));
}
"TITLE"을 검색 조건으로 지정하면 → title 컬럼에 대해 LIKE '%title10%'"CONTENT"이면 → content 컬럼에서 LIKE '%title10%'이렇게 조건을 코드 실행 시점에 구성할 수 있습니다.
Pageable paging = PageRequest.of(0, 5);
Page<Board> boardList = boardRepo.findAll(builder, paging);
QuerydslPredicateExecutor 덕분에, BooleanBuilder로 만든 조건을 넘겨서 페이징된 결과를 받을 수 있어요.SELECT * FROM board
WHERE title LIKE '%title10%'
LIMIT 5 OFFSET 0;
같은 동작을 해주는 셈입니다.
| 구성 요소 | 설명 |
|---|---|
QBoard | Board 엔티티를 QueryDSL이 자동 생성한 클래스, 필드 접근용 |
BooleanBuilder | 동적 WHERE 조건을 조립할 수 있는 쿼리 조건 빌더 |
QuerydslPredicateExecutor | findAll(BooleanBuilder) 사용 가능하게 해주는 인터페이스 |
PageRequest | 페이지 번호와 크기를 정해주는 페이징 객체 |
findAll(builder, paging) | 동적 조건 + 페이징 결과를 조회하는 메소드 |
BooleanBuilder 로 동적 WHERE 조건 생성if (searchCondition.equals("TITLE")) {
builder.and(qboard.title.contains(searchKeyword));
} else if (searchCondition.equals("CONTENT")) {
builder.and(qboard.content.like("%" + searchKeyword + "%"));
}
searchCondition 에 따라 조건 분기BooleanBuilder는 쿼리 실행 시점에 조건을 동적으로 조합Pageable paging = PageRequest.of(0, 5);
Page<Board> boardList = boardRepo.findAll(builder, paging);
getContent()로 실제 결과 꺼내오기List<Board> list = boardList.getContent();
Page<Board> 는 단순 리스트가 아니라 전체 페이지 정보도 포함되어 있음 getContent()로 실제 List<Board> 데이터 추출for(Board board:list) {
System.out.println(board);
}
이 코드는 QueryDSL + BooleanBuilder + Pageable을 조합하여
실행 시점에 조건이 유동적인 동적 검색 쿼리를 페이징 처리와 함께 구현한 예제입니다.
맞아요! 아주 잘 이해하셨어요 😊
이번 코드는 QueryDSL을 활용한 동적 쿼리 + 페이징 처리를 아주 깔끔하게 잘 구현한 예제예요.
마무리로 다시 정리해드릴게요:
BooleanBuilder 로 동적 WHERE 조건 생성if (searchCondition.equals("TITLE")) {
builder.and(qboard.title.contains(searchKeyword));
} else if (searchCondition.equals("CONTENT")) {
builder.and(qboard.content.like("%" + searchKeyword + "%"));
}
searchCondition 에 따라 조건 분기BooleanBuilder는 쿼리 실행 시점에 조건을 동적으로 조합Pageable paging = PageRequest.of(0, 5);
Page<Board> boardList = boardRepo.findAll(builder, paging);
getContent()로 실제 결과 꺼내오기List<Board> list = boardList.getContent();
Page<Board> 는 단순 리스트가 아니라 전체 페이지 정보도 포함되어 있음 getContent()로 실제 List<Board> 데이터 추출for(Board board:list) {
System.out.println(board);
}
이 코드는 QueryDSL + BooleanBuilder + Pageable을 조합하여
실행 시점에 조건이 유동적인 동적 검색 쿼리를 페이징 처리와 함께 구현한 예제입니다.
데이터가 많을 때 한 번에 다 불러오지 않고, 조금씩 나눠서 가져오는 방식이에요.
→ 웹사이트에서 흔히 보는 "다음 페이지", "1 2 3 4" 이런 거 전부 페이징이에요.
PageRequest.of(0, 5) 의미PageRequest.of(0, 5)
이건 0번째 페이지에서 5개 가져와라는 뜻이에요.
PageRequest.of(페이지 번호, 한 페이지에 가져올 데이터 개수)
| 표현식 | 의미 |
|---|---|
PageRequest.of(0, 5) | 1페이지를 뜻함 (0번 인덱스가 첫 페이지) |
PageRequest.of(1, 5) | 2페이지 |
PageRequest.of(2, 5) | 3페이지 |
PageRequest.of(0, 100) | 1페이지에서 100개씩 가져오겠다는 뜻 |
데이터가 총 12개 있다고 가정하면:
PageRequest.of(0, 5) → 1~5번 데이터PageRequest.of(1, 5) → 6~10번 데이터PageRequest.of(2, 5) → 11~12번 데이터즉, 페이지 번호는 가져오는 "시작 위치"를 의미하고
두 번째 인자는 한 페이지에 보여줄 개수를 말해요.
그래서 Spring Data JPA, QueryDSL, MyBatis 전부 페이징 기능을 갖고 있어요.
PageRequest.of(0, 5) → 1페이지, 5개씩PageRequest.of(1, 5) → 2페이지, 다음 5개pageInfo.getTotalPages(), getContent(), hasNext() 등을 통해 웹 UI와 연동돼요