minlog
article thumbnail

1. Querydsl

 

JPA 기본 쿼리 메서드의 기능과 @Query 어노테이션만으로 어려운 복잡한 검색 조건을 동적으로 쿼리를 생성해서 처리할 수 있는 기술이다.  

 

2. Querydsl 사용해보기

 

2.0.1. 1. 빌드 추가

라이브러리를 사용하기 위해서 build.gradle 파일에 내용을 추가해주어야 한다.

 

📑 build.gradle

<bash />
// 1. querydsl 추가 buildscript { ext { queryDslVersion = "5.0.0" } } plugins { id 'org.springframework.boot' version '2.7.10' id 'io.spring.dependency-management' version '1.0.15.RELEASE' //2. querydsl 추가 id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" id 'java' } 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' testImplementation 'org.springframework.boot:spring-boot-starter-test' // https://mvnrepository.com/artifact/mysql/mysql-connector-java implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.28' //3. querydsl 추가 implementation "com.querydsl:querydsl-jpa:${queryDslVersion}" implementation "com.querydsl:querydsl-apt:${queryDslVersion}" } //4. querydsl 추가 def querydslDir = "$buildDir/generated/querydsl" querydsl { jpa = true querydslSourcesDir = querydslDir } sourceSets { main.java.srcDir querydslDir } compileQuerydsl{ options.annotationProcessorPath = configurations.querydsl } configurations { compileOnly { extendsFrom annotationProcessor } querydsl.extendsFrom compileClasspath } tasks.named('test') { useJUnitPlatform() }

 

저장 후 파일을 갱신하면 Gradle에 추가된 파일들을 확인할 수 있는데 compileQuerydsl를 눌러주면 

폴더 : build > generated > querydsl > entity  폴더에 생성했던 entity 클레스가 Q가 붙어 생성이된다. 

 

 

2.0.2. 2. Repository 인터페이스 설정 추가

레파지토리 인터페이스에서 Querydsl 을 이용하려면 QuerydslPredicateExecutor 라는 인터페이스를 상속 받아야한다. 

<code />
public interface GuestbookRepository extends JpaRepository<Guestbook,Long>, QuerydslPredicateExecutor<Guestbook> { Guestbook getGuestbookByTitle(String title); }

 

 

 

2.1. 3. 테스트로 querydsl 사용 해보기

  • Q도메인 클래스를 얻어온다. 
  • 조건을 넣어주는 컨테이너를 생성한다. 
  • 조건은 필드와 결합해서 생성한다.
  • 생성한 조건은 and 또는 or을 사용하여 컨테이너에 넣어준다.
  • 레파지토리 인터페이스에서 사용하는 메서드와 함께 사용이 가능하다.

 

<code />
@Test @DisplayName("querydsl 사용하기") public void querydslTest(){ Pageable pageable = PageRequest.of(0,10, Sort.by("gno").descending()); QGuestbook qGuestbook = QGuestbook.guestbook; // Q도메인 클래스 얻어오기 String keyword = "1"; BooleanBuilder builder = new BooleanBuilder(); // 조건들을 넣어주는 컨테이너 생성 BooleanExpression expression = qGuestbook.title.contains(keyword); // 조건은 필드와 결합해서 생성 builder.and(expression); // 생성한 조건을 and 또는 or로 컨테이너에 넣어준다. Page<Guestbook> result = guestbookRepository.findAll(builder,pageable); // BooleanBuilder는 레파지토리에서 추가된 인터페이스의 findAll() 을 사용할 수 있다. result.stream().forEach(guestbook -> { System.out.println(guestbook); }); }

 

 

2.1.1. 🍫 더 많은 조건 추가 해보기

<bash />
private BooleanBuilder getSearch(PageRequestDto requestDto){ String type = requestDto.getType(); String keyword = requestDto.getKeyword(); QGuestbook qGuestbook = QGuestbook.guestbook; BooleanBuilder booleanBuilder= new BooleanBuilder(); //조건 생성 BooleanExpression expression = qGuestbook.gno.gt(0L); booleanBuilder.and(expression); //검색조건이 없을 경우 if (type == null || type.trim().length() == 0){ return booleanBuilder; } //검색조건 BooleanBuilder conditionGuilder = new BooleanBuilder(); if(type.contains("t")){ conditionGuilder.or(qGuestbook.title.contains(keyword)); } if(type.contains("c")){ conditionGuilder.or(qGuestbook.content.contains(keyword)); } if(type.contains("w")){ conditionGuilder.or(qGuestbook.writer.contains(keyword)); } booleanBuilder.and(conditionGuilder); return booleanBuilder; }
<code />
@Test @DisplayName(" querydsl 여러 조건 결합하여 검색하기") public void querydslTest2(){ PageRequestDto pageRequestDto = PageRequestDto.builder() .page(1) .size(10) .type("tc") .keyword("title5") .build(); PageResultDto<GuestbookDto,Guestbook> resultDto = service.getList(pageRequestDto); System.out.println("--------------------------"); for (GuestbookDto guestbookDto : resultDto.getDtoList()){ System.out.println(guestbookDto); } System.out.println("--------------------------"); resultDto.getPageList().forEach(i ->{ System.out.println(i); }); }

 

 

- 쿼리문 실행결과

<bash />
Hibernate: select guestbook0_.gno as gno1_0_, guestbook0_.moddate as moddate2_0_, guestbook0_.regdate as regdate3_0_, guestbook0_.content as content4_0_, guestbook0_.title as title5_0_, guestbook0_.writer as writer6_0_ from guestbook guestbook0_ where guestbook0_.gno>? and ( guestbook0_.title like ? escape '!' or guestbook0_.content like ? escape '!' ) order by guestbook0_.gno desc limit ? Hibernate: select count(guestbook0_.gno) as col_0_0_ from guestbook guestbook0_ where guestbook0_.gno>? and ( guestbook0_.title like ? escape '!' or guestbook0_.content like ? escape '!' )

 

profile

minlog

@jimin-log

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!