[게시판 프로젝트] API 구현(2) - Querydsl을 통해서 세부 검색 기능 구현
2024. 8. 16. 00:29ㆍCS/Spring
Querydsl을 통해서, Spring DATA REST로 구현할 수 없었던
좀 더 복잡하고 상세한 검색 기능을 구현합니다.
먼저, Querydsl을 사용하기 위한 설정을 해줍니다.
Querydsl 관련 플러그인
Gradle - Plugin: com.ewerk.gradle.plugins.querydsl
Version 1.0.10 (latest) 1.0.10 Created 02 July 2018. Plugin for generating QueryDSL model files. plugins { id("com.ewerk.gradle.plugins.querydsl") version "1.0.10" } buildscript { repositories { maven { url = uri("https://plugins.gradle.org/m2/") } } depen
plugins.gradle.org
- Qclasss는 자동생성이라 gitignore 설정해 주어야 한다.
Querydsl 의존성 추가 - springboot3.x.x
// Querydsl 추가
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
implementation 'com.querydsl:querydsl-core'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
//뷰 dependencies 추가
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
//사용자 커스텀 properties 도 문세세팅 가능 + IDE 지원
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
tasks.named('test') {
useJUnitPlatform()
}
// Querydsl 설정부
def generated = 'src/main/generated'
// querydsl QClass 파일 생성 위치를 지정
tasks.withType(JavaCompile) {
options.getGeneratedSourceOutputDirectory().set(file(generated))
}
// java source set 에 querydsl QClass 위치 추가
sourceSets {
main.java.srcDirs += [ generated ]
}
// gradle clean 시에 QClass 디렉토리 삭제
clean {
delete file(generated)
}
설정이 끝났으면,
레포지토리에 기본 검색에 대한 설정을 세팅한 다음
@Override를 통해서 검색에 대한 세부 내용을 구현합니다.
repository 설정
@RepositoryRestResource
public interface ArticleRepository extends
JpaRepository<Article, Long>,
QuerydslPredicateExecutor<Article>,
QuerydslBinderCustomizer<QArticle>
{
@Override //검색에 대한 세부 내용 구현
default void customize(QuerydslBindings bindings, QArticle root){
bindings.excludeUnlistedProperties(true);
bindings.including(root.title,root.content,root.hashtag,root.createdAt,root.createdBy);
bindings.bind(root.title).first(StringExpression::containsIgnoreCase);//쿼리문 : like '%${v}'
//bindings.bind(root.title).first(StringExpression::likeIgnoreCase);//쿼리문 : like '${v}'
bindings.bind(root.content).first(StringExpression::containsIgnoreCase);
bindings.bind(root.hashtag).first(StringExpression::containsIgnoreCase);
bindings.bind(root.createdAt).first(DateTimeExpression::eq); // 동일 검사
bindings.bind(root.createdBy).first(StringExpression::containsIgnoreCase);
}
}
@RepositoryRestResource
public interface ArticleCommentRepository extends
JpaRepository<ArticleComment, Long>,
QuerydslPredicateExecutor<ArticleComment>,
QuerydslBinderCustomizer<QArticleComment> {
@Override //검색에 대한 세부 내용 구현
default void customize(QuerydslBindings bindings, QArticleComment root) {
bindings.excludeUnlistedProperties(true);
bindings.including(root.content, root.createdAt, root.createdBy);
bindings.bind(root.content).first(StringExpression::containsIgnoreCase);
bindings.bind(root.createdAt).first(DateTimeExpression::eq); // 동일 검사
bindings.bind(root.createdBy).first(StringExpression::containsIgnoreCase);
}
}
뷰에서 Querydsl 연관 부분과 매커니즘
<form id="search-form">
<div class="row">
<div class="col-12">
<div class="row no-gutters">
<div class="col-lg-3 col-md-3 col-sm-12 p-0">
<label for="search-type" hidden>검색 유형</label>
<select class="form-control" id="search-type" name="searchType">
<option>제목</option>
<option>본문</option>
<option>id</option>
<option>닉네임</option>
<option>해시태그</option>
</select>
</div>
<div class="col-lg-8 col-md-6 col-sm-12 p-0">
<label for="search-value" hidden>검색어</label>
<input type="text" placeholder="검색어..." class="form-control" id="search-value" name="searchValue">
</div>
<div class="col-lg-1 col-md-3 col-sm-12 p-0">
<button type="submit" class="btn btn-base">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</button>
</div>
</div>
</div>
</div>
</form>
1. 검색 폼
<select id="search-type" name="searchType">:
- 사용자가 검색하려는 유형을 선택할 수 있습니다(예: 제목, 본문, ID, 닉네임, 해시태그).
- 이 값은 searchType이라는 이름으로 서버로 전송됩니다.
<input type="text" id="search-value" name="searchValue">
- 사용자가 입력한 검색어입니다.
- 이 값은 searchValue라는 이름으로 서버로 전송됩니다.
<button type="submit">
- 검색 폼을 제출합니다. 사용자가 검색 유형과 검색어를 입력하고 이 버튼을 클릭하면, 폼에 입력된 데이터가 서버로 전송됩니다.
2. QueryDSL과의 연관성
- 사용자가 폼에 입력한 searchType과 searchValue가 서버로 전송되면, 백엔드에서 이 데이터를 받아 QueryDSL을 사용하여 데이터베이스에서 필요한 게시글을 검색합니다.
- 이 검색 작업은 ArticleRepository와 ArticleCommentRepository의 customize 메소드에서 정의된 QueryDSL 바인딩 설정과 연관이 있습니다. 예를 들어, 사용자가 "제목"으로 검색을 선택하고 검색어를 입력하면, QueryDSL이 이 조건을 사용하여 제목에 검색어가 포함된 게시글을 찾습니다.
3. 서버 측에서의 처리
- 서버 측 코드, Repository의 QueryDSL 설정이 실제로 검색 작업을 처리합니다.
- 이 설정은 사용자가 선택한 검색 유형과 검색어에 따라 동적으로 쿼리를 생성하여 데이터베이스에서 결과를 가져오는 역할을 합니다.
'CS > Spring' 카테고리의 다른 글
| [게시판 프로젝트] 뷰 구현(1) - 타임리프를 사용하여 게시판/게시글 페이지 구현 (0) | 2024.08.17 |
|---|---|
| [게시판 프로젝트] API 구현(1) - Spring DATA REST를 통해 (0) | 2024.08.16 |
| [게시판 프로젝트] repository, JPAConfig 생성 (0) | 2024.08.15 |
| [게시판 프로젝트] IntelliJ spring boot DB 접근 설정하기 - MySQL (0) | 2024.08.15 |
| [게시판 프로젝트] 도메인 설계하기 - Java 클래스로 도메인 표현하기 (0) | 2024.08.15 |