Querydsl 이용 시 코드 내부에서 상황에 맞는 쿼리 생성이 가능하지만 이를 위해서는
작성된 엔티티 클래스를 그대로 사용하는 것이 아니라 Q도메인 이라는 것을 이용해야 함
그리고 이를 작성하기 위해서 Quertdsl 라이브러리를 이용해서 엔티티 클래스를 Q도메인 클래스로 변환하는 방식 이용
-> 추가적인 설정 필요
1. build.gradle 에 코드 추가
plugins {
id 'org.springframework.boot' version '2.4.5'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
id 'war'
// Querydsl 사용을 위해 추가
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compile group: 'org.mariadb.jdbc', name: 'mariadb-java-client'
compile group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-java8time'
//Querydsl 사용을 위해 추가
implementation 'com.querydsl:querydsl-jpa'
}
test {
useJUnitPlatform()
}
// Querydsl 사용을 위해 추가
def querydslDir = "$buildDir/generated/querydsl"
querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main.java.srcDir querydslDir
}
configurations {
querydsl.extendsFrom compileClasspath
}
compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}
2. 적용 후 compileQuerydsl 실행
3. GuestbookRepository -> QuerydslPredicateExecutor 인터페이스 상속
package com.example.chapter4.repository;
import com.example.chapter4.Entity.Guestbook;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
//JpaRepository<Guestbook,Long> -> <Table명, 기본키 데이터 타입>
//QuerydslPredicateExecutor<Guestbook> -> findAll : Optional을 리턴 / findOne : List, Page 등으로 리턴
public interface GuestbookRepository extends JpaRepository<Guestbook, Long>, QuerydslPredicateExecutor<Guestbook> {
}
4. GuestbookRepositoryTests 생성 후 실행
package com.example.chapter4.repository;
import com.example.chapter4.Entity.Guestbook;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.stream.IntStream;
@SpringBootTest
public class GuestbookRepositoryTests {
@Autowired
private GuestbookRepository guestbookRepository;
@Test
public void insertDummies(){
IntStream.rangeClosed(1,300).forEach(i->{
Guestbook guestbook = Guestbook.builder()
.title("Title...."+i)
.content("Contnet...."+i)
.writer("user...."+i%10)
.build();
System.out.println(guestbookRepository.save(guestbook));
});
}
}
5. 데이터 생성 확인
6. Guestbook 클래스에 수정 메서드 추가
package com.example.chapter4.Entity;
import lombok.*;
import javax.persistence.*;
@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Guestbook extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long gno;
@Column(length = 100, nullable = false)
private String title;
@Column(length = 1500, nullable = false)
private String content;
@Column(length = 50, nullable = false)
private String writer;
// 엔티티 클래스는 가능하면 setter 관련 기능을 만들지 않는 것이 권장사항이지만
// 필요에 따라서 수정 기능을 만들기도 함
// 아래는 제목과 내용을 수정할 수 있도록 메서드 추가
public void changeTitle(String title){
this.title = title;
}
public void changeContent(String content){
this.content = content;
}
}
7. 수정 시간 테스트
GuestbookRepositoryTests.java
@Test
public void updateTest(){
//존재하는 번호로 테스트
Optional<Guestbook> result = guestbookRepository.findById(300L);
if(result.isPresent()){
Guestbook guestbook = result.get();
guestbook.changeTitle("changeTitle...");
guestbook.changeContent("changeContent...");
guestbookRepository.save(guestbook);
}
}
Querydsl 사용법
- booleanBuilder 생성
- 조건에 맞는 구문은 Querydsl에서 사용하는 Predicate 타입의 함수 생성
- BooleanBuilder에 작성된 Predicate 추가하고 실행
8. 단일 항목 검색 테스트
GuestbookRepositoryTests.java
@Test
public void testQuery1(){
Pageable pageable = PageRequest.of(0,10, Sort.by("gno").descending());
// 동적 처리를 위한 Q도메인 클래스 얻어오기
// Q도메인 클래스 이용 시 엔티티 클래스에 선언된 title, content 같은 필드들을 변수로 활용 가능
QGuestbook qGuestbook = QGuestbook.guestbook; // 1
String keyword = "1";
// BooleanBuilder는 where문에 들어가는 조건들을 넣어주는 컨테이너
BooleanBuilder builder = new BooleanBuilder(); // 2
// 원하는 조건은 필드 값과 같이 결합해서 생성
// BooleanBuilder 안에 들어가는 값은 com.querydsl.core.types.Predicate 타입
BooleanExpression expression = qGuestbook.title.contains(keyword); // 3
// 만들어진 조건은 where 문에 and나 or같은 키워드와 결합
builder.and(expression); // 4
// BooleanBuilder는 GuestbookRepository에 추가된
// QuerydslPredicateExcutor 인터페이스의 findAll() 사용 가능
Page<Guestbook> result = guestbookRepository.findAll(builder,pageable); // 5
result.stream().forEach(guestbook -> {
System.out.println(guestbook);
});
}
9. 다중 항목 검색 테스트
GuestbookRepositoryTests.java
@Test
public void testQuery2() {
Pageable pageable = PageRequest.of(0, 10, Sort.by("gno").descending());
QGuestbook qGuestbook = QGuestbook.guestbook;
String keyword = "1";
BooleanBuilder builder = new BooleanBuilder();
//exTitle like %1%
BooleanExpression exTitle = qGuestbook.title.contains(keyword);
//exContent like %1%
BooleanExpression exContent = qGuestbook.content.contains(keyword);
// exTitle like %1% or exContent like %1%
BooleanExpression exAll = exTitle.or(exContent); // 1----------------
builder.and(exAll); //2-----
//qGuestbook.gno > 0L
builder.and(qGuestbook.gno.gt(0L)); // 3-----------
Page<Guestbook> result = guestbookRepository.findAll(builder, pageable);
result.stream().forEach(guestbook -> {
System.out.println(guestbook);
});
}
'IntelliJ > Spring boot' 카테고리의 다른 글
[Springboot]게시판 만들기 3장 서비스 계층과 DTO - hoyhi (0) | 2021.04.26 |
---|---|
[Springboot]게시판 만들기 1장 프로젝트 설정 및 테이블 생성 - hoyhi (0) | 2021.04.25 |
[Spring boot] Entitiy, DTO, VO 차이 -hoyhi-tistory (0) | 2021.04.03 |
Spring Model 객체 (0) | 2021.02.21 |
스프링부트 프로젝트 생성 (0) | 2021.02.21 |