Querydsl

바그다드·2023년 3월 27일
0

Querydsl

쿼리를 Java로 type-safe하게 개발할 수 있게 지원해주는 프레임워크

  • 간단한 예시를 보자
String sql = "select * from item wherename like ?"
  • 위의 코드를 실행시키면 에러가 발생할 것이다. wherename 이 부분에 의해서
  • 하지만 컴파일은 될 것이고, 이를 방치했다가 실제 서비스에서 위의 쿼리를 사용해야 하는 상황이 발생하면 이미 늦어버린다.
  • 이를 Querydsl이 잡아주는데
    Type-safe하게라는 말은 컴파일하는 시점에 에러를 체크할 수 있게 만들어 준다는 것이다!!!

Querydsl 설정

  • build.gradle
// dependency
//Querydsl 추가
implementation 'com.querydsl:querydsl-jpa'
annotationProcessor "com.querydsl:querydsl-apt:$
{dependencyManagement.importedProperties['querydsl.version']}:jpa"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
// 이 코드를 추가하면 gradle clean을 실행할 때 src/main/generated 파일도 삭제해준다
// 이건 dependencies 바깥에 붙여주자
clean {
delete file('src/main/generated')
}

이 두개의 코드를 추가해주자

  • 이후에 Q타입을 생성하는 방법은
  1. Gradle방법 : Gradle을 통해서 빌드

    • Gradle IntelliJ 사용법
      Gradle -> Tasks -> build -> clean
      Gradle -> Tasks -> other -> compileJava

    • Gradle 콘솔 사용법
      ./gradlew clean compileJava

    • build -> generated -> sources -> annotationProcessor -> java/main
      여기에 Q타입이 생성되면 완료!

  2. IntelliJ IDEA방법 : intelliJ가 직접 자바를 실행해서 빌드

    • Build -> Build Project 또는 Build -> Rebuild을 실행
    • src/main/generated
      여기에 Q타입이 생성되면 완료!

Querydsl 적용

@Repository
@Transactional
public class JpaItemRepositoryV3 implements ItemRepository {

    private final EntityManager em;
    private final JPAQueryFactory query;

    public JpaItemRepositoryV3(EntityManager em) {
        this.em = em;
        this.query = new JPAQueryFactory(em);
    }
    
    // Querydsl 적용 전
     @Override
    public List<Item> findAll(ItemSearchCond cond) {
        String itemName = cond.getItemName();
        Integer maxPrice = cond.getMaxPrice();

        if (StringUtils.hasText(itemName) && maxPrice != null) {
//            return repository.findByItemNameLikeAndPriceLessThanEqual("%" + itemName + "%", maxPrice);
            return repository.findItems("%" + itemName + "%", maxPrice);
        } else if (StringUtils.hasText(itemName)) {
            return repository.findByItemNameLike("%" + itemName + "%");
        } else if (maxPrice != null) {
            return repository.findByPriceLessThanEqual(maxPrice);
        } else {
            return repository.findAll();
        }
    }
    
    // Querydsl 적용 후
    // 모든 Item 찾기 또는 조건에 따라 찾기
    @Override
    public List<Item> findAll(ItemSearchCond cond) {

        String itemName = cond.getItemName();
        Integer maxPrice = cond.getMaxPrice();

        QItem item = QItem.item;
        
        return query
                .select(item)
                .from(item)
                .where(likeItemName(itemName), maxPrice(maxPrice))
                .fetch();
    }

    private BooleanExpression likeItemName(String itemName) {
        if(StringUtils.hasText(itemName)){
            return QItem.item.itemName.like("%" + itemName + "%");
        }
        return null;
    }

    private BooleanExpression maxPrice(Integer maxPrice) {
        if (maxPrice != null) {
            return QItem.item.price.loe(maxPrice);
        }
        return null;
    }

}
  • Querydsl을 적용한 메서드를 보면 쿼리 유사한 형태를 띄고 있어 눈에 쉽게 들어온다.
    또한 이를 자바로 구현했기 때문에 에러가 발생하면 컴파일 에러가 발생하여 문제를 쉽게 인지할 수 있다.
    - 컴파일 에러가 제일 착한 에러
  • 또 likeItemName(), maxPrice()을 메서드로 추출하였기 때문에 다른 쿼리에서도 재사용이 가능하다는 장점이 있다!!
  • Querydsl을 사용하려면 JPAQueryFactory가 필요한데 JPAQueryFactory 얘는 또 JPA쿼리인 JPQL을 생성하는 애이기 때문에 EntityManager가 필요하다.

예외변환

  • Querydsl은 스프링 예외 추상화를 지원하지 않지만, @Repository가 스프링 예외 추상화를 대신 처리해준다.

새로 하는 프로젝트에서 JPA Querydsl을 사용할 일이 생겨서 급하게 진도를 바꿔 먼저 수강하였다. 내일부터 다시 차근차근 진도 나가야겠다.

profile
꾸준히 하자!

0개의 댓글