본문에서는 Restful API 테스트와 구현을 해보려한다.
먼저 https://start.spring.io/로 들어가서
dependencies에서
Rest Repositories와
Rest Repositories HAL Explorer를 찾아준다.
그 후, build.gradle에서
의존성에
// spring rest data
implementation 'org.springframework.boot:spring-boot-starter-data-rest'
implementation 'org.springframework.data:spring-data-rest-hal-explorer'
을 추가해주겠다.
더해서, application.yaml 파일에
spring:
jpa:
data.rest:
base-path: /api
detection-strategy: annotated를 추가해준다.
https://docs.spring.io/spring-data/rest/docs/current/reference/html/#getting-started.basic-settings
이 곳을 참조해보면,
이런식으로 나온다
QueryDSL 추가
QueryDSL을 사용하는 이유.
Spring Data JPA가 기본적으로 제공해주는 CRUD 기능과 쿼리 기능을 사용하게 되더라도,
로직이 복잡한 쿼리문이나 좀 더 유동적인 쿼리를 사용하려면 QueryDSL은 필수불가결이다.
먼저 build.gradle에 의존성을 추가해준다.
buld.gradle
// queryDSL
implementation "com.querydsl:querydsl-jpa"
implementation "com.querydsl:querydsl-core"
implementation "com.querydsl:querydsl-collections"
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" // querydsl JPAAnnotationProcessor 사용 지정
annotationProcessor "jakarta.annotation:jakarta.annotation-api" // java.lang.NoClassDefFoundError (javax.annotation.Generated) 대응 코드
annotationProcessor "jakarta.persistence:jakarta.persistence-api" // java.lang.NoClassDefFoundError (javax.annotation.Entity) 대응 코드
각 의존성들에 대한 자세한 공부는 추후에 할 예정이다.
대강 중요한 것들만 먼저 나열하자면,
annotationProcessor "jakarta.annotation:jakarta.annotation-api" // java.lang.NoClassDefFoundError (javax.annotation.Generated) 대응 코드
annotationProcessor "jakarta.persistence:jakarta.persistence-api" // java.lang.NoClassDefFoundError (javax.annotation.Entity) 대응 코드
이 둘은 querydsl-apt가 JPA @Entity 등의 annotation을 알 수 있도록, 추가해주어야 한다.
build.gradle
// 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)
}
Querydsl은 QClass를 사용하기 때문에 querydsl에서 자동으로 생성해줄 QClass 디렉토리를
build.gradle에 지정해준다.
PostRepository.java
public interface PostRepository extends
JpaRepository<Post, Long>,
QuerydslPredicateExecutor<Post>, // QueryDSL 에 탑재되어있는 기본 검색기능 지원, 부분 검색만 되고 Exact Match만 가능.
QuerydslBinderCustomizer<QPost> { // 그래서 Customizer 기능을 사용함.
Querydsl에서 제공하는 검색기능을 활용하기 위해
QuerydslPredicateExecutor와 QuerydslBinderCustomizer을 추가해준다.
여기서 QuerydslPredicateExecutord의 argument에는 일반 클래스를,
QuerydslBinderCustomizer의 argument에 QClass를 넣는 것을 유의해야한다!!
default void customize(QuerydslBindings bindings, QPost root) {
bindings.excludeUnlistedProperties(true);
bindings.including(root.title, root.hashtag, root.content, root.createdBy, root.createdDate);
bindings.bind(root.title).first(StringExpression::containsIgnoreCase);
bindings.bind(root.hashtag).first(StringExpression::containsIgnoreCase);
bindings.bind(root.content).first(StringExpression::containsIgnoreCase);
bindings.bind(root.createdBy).first(StringExpression::containsIgnoreCase);
bindings.bind(root.createdDate).first(DateTimeExpression::eq);
}
그리고 binding을 이용하여 게시글의 제목, 해시태그, 내용, 작성자, 작성일(추후 제거하거나 수정)을
검색할 수 있는 customize 메소드를 추가해준다.
QuerydslPredicateExecutor만 사용할 경우 , Exact Matching으로 검색하기 때문에, 대소문자 구별은
하지않지만, 보통 사람들이 게시글이 검색할 때 쓰는 부분검색은 되지 않는다.
고로 QuerydslBinderCustomizer를 써야 일반적인 %Like 검색을 할 수 있다.
default void customize(QuerydslBindings bindings, QComment root){
bindings.excludeUnlistedProperties(true);
bindings.including(root.content, root.createdBy, root.createdDate);
bindings.bind(root.content).first(StringExpression::containsIgnoreCase);
bindings.bind(root.createdBy).first(StringExpression::containsIgnoreCase);
bindings.bind(root.createdDate).first(DateTimeExpression::eq);
}
.gitignore
마지막으로 QClass파일들을 gitignore에 추가해 쓸데 없는 충돌이 일어나지 않게 방지해주자.
### Querydsl
/src/main/generated