관리 메뉴

bright jazz music

guestbook : 04. querydsl 테스트 본문

Framework/Spring

guestbook : 04. querydsl 테스트

bright jazz music 2022. 7. 1. 09:02

이전글

2022.06.30 - [분류 전체보기] - guestbook : 03. 자동 일자/시간 처리(등록/수정 등) +Querydsl (2)

 

여기서 querydsl을 사용할 테스트

 

  • '제목/내용/작성자'와 같이 단일 항목으로 검색하는 경우 (단일 항목 검색 테스트)
  • '제목 + 내용', '내용 + 작성자' 또는 '제목 + 작성자'와 같이 2개의 항목으로 검색하는 경우
  • '제목 + 내용 + 작성자'와 같이 3개 항목으로 검색하는 경우

1. Querydsl을 사용

 

실제 개발에서는 엔티티 클래스에 더 많은 멤버 변수들이 존재할 수 있기 때문에 조합의 수는 훨씬 더 증가한다. 이런 경우 Querydsl을 사용할 수 있다.

 

2. Querydsl 사용법

  1. BooleanBuilder 생성
  2. 조건에 맞는 구문에 대해서 Querydsl에서 사용하는 Predicate 타입의 함수를 생성
  3. BooleanBuilder에 작성된 Predicate를 추가하고 실행

*predicate: n.서술부, 서술어 verb.서술하다, 단언하다, 입각하다

 

3. 테스트

3-1. 단일 항목 검색 테스트

//GuestbookRepositoryTests.java
package com.example.guestbook.repository;

import com.example.guestbook.entity.Guestbook;
import com.example.guestbook.entity.QGuestbook;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.dsl.BooleanExpression;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import java.util.Optional;
import java.util.stream.IntStream;

@SpringBootTest
public class GuestbookRepositoryTests {

    @Autowired
    private GuestbookRepository guestbookRepository; //의존성 주입

    @Test
    public void insertDummies(){
        //테스트 데이터 300개 입력
        IntStream.rangeClosed(1, 300).forEach(i -> {
            Guestbook guestbook = Guestbook.builder()
                    .title("Title...." + i)
                    .content("Content..." + i)
                    .writer("user" + (i %10))
                    .build();

            System.out.println(guestbookRepository.save(guestbook));
        });

    }

    @Test //<== guestbook 업데이트 테스트를 위해 추가
    public void updateTest(){
        Optional<Guestbook> result = guestbookRepository.findById(300L);
        // DB에 존재하는 번호인 300번으로 테스트
        //Optional : If non-null, the value; if null, indicates no value is present.
        // isPresent() 또는 isEmpty()로 확인.

        System.out.println("result.isPresent())="+ result.isPresent());

        if(result.isPresent()) {
            Guestbook guestbook = result.get();
            guestbook.changeTitle("Change Title!!!!!!!!!!!!!!!");
            guestbook.changeContent("change content!!!!!!!!!!!!!!!");

            guestbookRepository.save(guestbook);
        }
    }
    
    ///// Querydsl 단일 항목 검색 테스트
    @Test
    public void testQuery1() {
        Pageable pageable = PageRequest.of(0, 10, Sort.by("gno").descending());		// gno단일항목

        QGuestbook qGuestbook = QGuestbook.guestbook;                               //1
        String keyword = "1";
        
        BooleanBuilder builder = new BooleanBuilder();                              //2
        BooleanExpression expression = qGuestbook.title.contains(keyword);          //3
        // com.querydsl.core.types.dsl
        
        builder.and(expression);                                                    //4
        
        Page<Guestbook> result = guestbookRepository.findAll(builder, pageable);    //5
        
        result.stream().forEach(guestbook -> {
            System.out.println(guestbook);
        });
    }
}

 

1. 동적으로 처리하기 위해 Qdomain 클래스를 얻어온다.
	이를 사용하면 엔티티 클래스에 선언된  title, content 같은 필드들을 변수로 활용할 수 있다.

2. BooleanBuilder는 Where 문에 들어가는 조건들을 넣어주는 컨테이너 역할을 한다.

3. 원하는 조건을 필드 값과 결합하여 생성한다.
	BooleanBuilder 내에 들어가는 값은 com.querydsl.core.types.Predicate
    또는 com.querydsl.core.types.dsl타입이어야 한다.

4. 조합한 조건을 where문에 and나 or와 같은 키워드와 결합한다.

5. BooleanBuilder는 GuestbookRepository에 추가된 
	QuerydslPredicateExcutor 인터페이스의	findAll()을 사용할 수 있다.

녹색 화살표를 눌러 테스트 실행

 

==> 이를 통해서 페이지 처리와 동시에 검색 처리가 가능해진다.

 

콘솔:

 

3-2. 다중 항목 검색 테스트 

복합조건: 여러 조건이 결합된 형태

 

테스트 내용:

'title' 또는 'content'에 특정 keyword가 있고 'gno'가 0보다 큰 경우를 조회하는 복합조건을 처리

 

복합조건을 처리하는 경우에는 BooleanBuilder를 사용하는 것이 좋다. and() 또는 or() 메서드의 파라미터로  BooleanBuilder를 전달할 수 있기 때문이다. 이로써 복합적인 쿼리를 생성할 수 있다.

 

//GuestbookRepositoryTests.java
package com.example.guestbook.repository;

import com.example.guestbook.entity.Guestbook;
import com.example.guestbook.entity.QGuestbook;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.dsl.BooleanExpression;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import java.util.Optional;
import java.util.stream.IntStream;

@SpringBootTest
public class GuestbookRepositoryTests {

    @Autowired
    private GuestbookRepository guestbookRepository; //의존성 주입

    @Test
    public void insertDummies(){
        //테스트 데이터 300개 입력
        IntStream.rangeClosed(1, 300).forEach(i -> {
            Guestbook guestbook = Guestbook.builder()
                    .title("Title...." + i)
                    .content("Content..." + i)
                    .writer("user" + (i %10))
                    .build();

            System.out.println(guestbookRepository.save(guestbook));
        });

    }

    @Test //<== guestbook 업데이트 테스트를 위해 추가
    public void updateTest(){
        Optional<Guestbook> result = guestbookRepository.findById(300L);
        // DB에 존재하는 번호인 300번으로 테스트
        //Optional : If non-null, the value; if null, indicates no value is present.
        // isPresent() 또는 isEmpty()로 확인.

        System.out.println("result.isPresent())="+ result.isPresent());

        if(result.isPresent()) {
            Guestbook guestbook = result.get();
            guestbook.changeTitle("Change Title!!!!!!!!!!!!!!!");
            guestbook.changeContent("change content!!!!!!!!!!!!!!!");

            guestbookRepository.save(guestbook);
        }
    }

    /////Querydsl 단일 항목 검색 테스트
    @Test
    public void testQuery1() {
        Pageable pageable = PageRequest.of(0, 10, Sort.by("gno").descending()); //gno 단일항목

        QGuestbook qGuestbook = QGuestbook.guestbook;                               //1
        String keyword = "1";

        BooleanBuilder builder = new BooleanBuilder();                              //2
        BooleanExpression expression = qGuestbook.title.contains(keyword);          //3
        // com.querydsl.core.types.dsl

        builder.and(expression);                                                    //4

        Page<Guestbook> result = guestbookRepository.findAll(builder, pageable);    //5

        result.stream().forEach(guestbook -> {
            System.out.println(guestbook);
        });
    }

    

    /////Querydsl 다중 항목 검색 테스트
    @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();

        BooleanExpression exTitle = qGuestbook.title.contains(keyword);

        BooleanExpression exContent = qGuestbook.content.contains(keyword);

        BooleanExpression exAll = exTitle.or(exContent); // 1 -------------------------

        builder.and(exAll); // 2 -------------------------

        builder.and(qGuestbook.gno.gt(0L)); // 3 -------------------------

        Page<Guestbook> result = guestbookRepository.findAll(builder, pageable);

        result.stream().forEach(guestbook -> {
            System.out.println(guestbook);
        });

    }

}

(부분 1) exTitle, exContent : BooleanExpression을 결합한다.

(부분2) 이를 BooleanBuilder에 추가

(부분3) 'gno'가 0보다 크다는 조건 추가

 

쿼리문의 where절 내부에 or와 같은 키워드로 생성된 쿼리를 확인 가능.

 

만약 '제목+내용+작성자' 를 처리하고 싶다면 exTitle, exContent와 동일하게 BooleanExpression을 생성하고 'or' 조건으로 결합하면 된다. 이 밑은 그냥 참고만 할 것.

 

 


/////Querydsl 다중 항목 검색 테스트2
@Test
public void testQuery3(){
    Pageable pageable = PageRequest.of(0, 10, Sort.by("gno").descending());

    QGuestbook qGuestbook = QGuestbook.guestbook;

    String keyword = "1";

    BooleanBuilder builder = new BooleanBuilder();

    BooleanExpression exTitle = qGuestbook.title.contains(keyword);

    BooleanExpression exContent = qGuestbook.content.contains(keyword);

    BooleanExpression exWriter = qGuestbook.writer.contains(keyword); //writer를 추가해 보았다.

    BooleanExpression exAll = exTitle.or(exContent).or(exWriter); // 1 -------------------------

    builder.and(exAll); // 2 -------------------------

    builder.and(qGuestbook.gno.gt(0L)); // 3 -------------------------


    Page<Guestbook> result = guestbookRepository.findAll(builder, pageable);

    result.stream().forEach(guestbook -> {
        System.out.println(guestbook);
    });

}

 

Comments