SpringBoot QueryDSL JPA 사용하기

후니·2023년 3월 5일

스프링

목록 보기
1/5

이번 스프링부트를 공부하며 상품정보를 보여주는 게시판의 검색기능을 구현중 기존 JPA만 가지고는 동적쿼리를 구현하는데 한계를 느끼고 방법을 찾는중 QueryDSL이라는 것을 찾았고
JPQL등 다른 동적쿼리 방식도 있었지만 QueryDSL이 제일 코드가 갈끔해서 사용하기로 했다.

QueryDSL이란?

Querydsl 정적 타입을 이용해서 SQL과 같은 쿼리를 생성할 수 있도록 해 주는 프레임워크다.

QueryDSL구현 해보기

build.gradle 설정

dependencies {
	... 
	implementation 'com.querydsl:querydsl-jpa'
	implementation 'com.querydsl:querydsl-apt'
	annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
	annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
	annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
}

def querydslSrcDir = 'src/main/generated'
sourceSets {
  main {
    java {
      srcDirs += [ querydslSrcDir ]
    }
  }
}

compileJava {
    options.compilerArgs << '-Aquerydsl.generatedAnnotationClass=javax.annotation.Generated'
}

tasks.withType(JavaCompile) {
	options.generatedSourceOutputDirectory = file(querydslSrcDir)
}

clean {
  delete file(querydslSrcDir)
}

Config파일 설정

import com.querydsl.jpa.impl.JPAQueryFactory;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuerydslConfig {
    @PersistenceContext
    private EntityManager entityManager;

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(entityManager);
    }
}

ProductService.java 구현

public List<ProductEntity> getProduct(SearchDto request, Integer memberNo) {

     List<ProductEntity> list = productRepository.findBySearch(memberNo, request);

     return list;
}

ProductRepository.java 구현

public interface ProductRepository extends JpaRepository<ProductEntity, Integer>, ProductRepositoryCustom {
}

ProductRepositoryCustom.java 구현

public interface ProductRepositoryCustom {
    public List<ProductEntity> findBySearch(Integer memberNo, SearchDto request);   
}

ProductRepositoryImpljava 구현
파일명은 Impl로 끝나야함

import java.time.LocalDate;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import static com.example.runi.member.domain.entity.QProductEntity.product;
import com.example.runi.member.domain.dto.SearchDto;
import com.example.runi.member.domain.entity.ProductEntity;

@Repository
public class ProductRepositoryImpl implements ProductRepositoryCustom {
    private final JPAQueryFactory queryFactory;

    public ProductRepositoryImpl(JPAQueryFactory jpaQueryFactory) {
        this.queryFactory = jpaQueryFactory;
    }

    public List<ProductEntity> findBySearch(Integer memberNo, SearchDto reqeust) {

        return queryFactory
                    .selectFrom(product)
                    .where(
                        product.memberNo.eq(memberNo),
                        select(reqeust), 
                        date(reqeust)
                    )
                    .orderBy(product.no.desc())
                    .fetch();
    }

	//조건검색
    private BooleanExpression select(SearchDto reqeust) {
        
        String select = reqeust.getSelect();
        String search = reqeust.getSearch();

        if(search.isEmpty()) return null;

        try {

            if(select.equals("0")) {
                return product.no.eq(Integer.parseInt(search));
            } else if(select.equals("1")) {
                return product.productName.eq(search);
            } else if(select.equals("2")) {
                return product.price.eq(Integer.parseInt(search));
            } else if(select.equals("3")) {
                return product.saveDate.eq(LocalDate.parse(search));
            } else {
                return null;
            }

        } catch(Exception e) {
            return null;
        }
    }
    
    //날짜 검색
    private BooleanExpression date(SearchDto reqeust) {
        
        String startDate = reqeust.getStartDate();
        String endDate = reqeust.getEndDate();

        if(!startDate.isEmpty() && endDate.isEmpty()) {
            return product.saveDate.goe(LocalDate.parse(startDate));
        }else if(startDate.isEmpty() && !endDate.isEmpty()) {
            return product.saveDate.loe(LocalDate.parse(endDate));
        }else if(!startDate.isEmpty() || !endDate.isEmpty()) {
            return product.saveDate.between(LocalDate.parse(startDate), LocalDate.parse(endDate));
        }else { 
            return null;
        }
    }
}

0개의 댓글