스터디/2023_스프링부트

[study] 스프링 DB 2편 - 7. Querydsl

Hotsan 2023. 8. 28. 13:23

김영한님의 스프링 DB 2편 - 데이터 접근 활용 기술을 듣고 정리한 내용입니다.

QueryDSL 이란

QueryDSL은 하이버네이트 쿼리 언어(HQL: Hibernate Query Language)의 쿼리를 타입에 안전하게 생성 및 관리해주는 프레임워크이다.

QueryDSL은 정적 타입을 이용하여 SQL과 같은 쿼리를 생성할 수 있게 해 준다.

 

자바 백엔드 기술은 Spring Boot와 Spring Data JPA를 함께 사용한다. 하지만, 복잡한 쿼리, 동적 쿼리를 구현하는 데 있어 한계가 있다. 이러한 문제점을 해결할 수 있는 것이 QueryDSL이다.

 

QueryDSL이 등장하기 이전에는 Mybatis, JPQL, Criteria 등 문자열 형태로 쿼리문을 작성하여 컴파일 시에 오류를 발견하는 것이 불가능했다.

하지만, QueryDSL은 자바 코드로 SQL 문을 작성할 수 있어 컴파일 시에 오류를 발생하여 잘못된 쿼리가 실행되는 것을 방지할 수 있다.

 

QueryDSL 장점

  • 문자가 아닌 코드로 쿼리를 작성할 수 있어 컴파일 시점에 문법 오류를 확인할 수 있다.
  • 인텔리제이와 같은 IDE의 자동 완성 기능의 도움을 받을 수 있다.
  • 복잡한 쿼리나 동적 쿼리 작성이 편리하다.
  • 쿼리 작성 시 제약 조건 등을 메서드 추출을 통해 재사용할 수 있다.
  • JPQL 문법과 유사한 형태로 작성할 수 있어 쉽게 적응할 수 있다.

 

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);
    }

    @Override
    public Item save(Item item) {
        em.persist(item);
        return item;
    }

    @Override
    public void update(Long itemId, ItemUpdateDto updateParam) {
        Item findItem = em.find(Item.class, itemId);
        findItem.setItemName(updateParam.getItemName());
        findItem.setPrice(updateParam.getPrice());
        findItem.setQuantity(updateParam.getQuantity());
    }

    @Override
    public Optional<Item> findById(Long id) {
        Item item = em.find(Item.class, id);
        return Optional.ofNullable(item);
    }

    public List<Item> findAllOld(ItemSearchCond cond) {

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

        QItem item = QItem.item;
        BooleanBuilder builder = new BooleanBuilder();
        if (StringUtils.hasText(itemName)) {
            builder.and(item.itemName.like("%" + itemName + "%"));
        }
        if (maxPrice != null) {
            builder.and(item.price.loe(maxPrice));
        }

        List<Item> result = query
                .select(item)
                .from(item)
                .where(builder)
                .fetch();

        return result;
    }

    @Override
    public List<Item> findAll(ItemSearchCond cond) {

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

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

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

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

Querydsl을 사용하려면 JPAQueryFactory 가 필요하다. JPAQueryFactory 는 JPA 쿼리인 JPQL을 만들기 때문에 EntityManager 가 필요하다.
설정 방식은 JdbcTemplate 을 설정하는 것과 유사하다

 

save(), update(), findById()

기본 기능들은 JPA가 제공하는 기본 기능을 사용한다.

 

findAllOld

Querydsl을 사용해서 동적 쿼리 문제를 해결한다.
BooleanBuilder 를 사용해서 원하는 where 조건들을 넣어주면 된다.
이 모든 것을 자바 코드로 작성하기 때문에 동적 쿼리를 매우 편리하게 작성할 수 있다

 

findAll

List<Item> result = query
    .select(item)
    .from(item)
    .where(likeItemName(itemName), maxPrice(maxPrice))
    .fetch();

Querydsl에서 where(A,B) 에 다양한 조건들을 직접 넣을 수 있는데, 이렇게 넣으면 AND 조건으로 처리된다.
where() 에 null 을 입력하면 해당 조건은 무시한다.

이 코드의 또 다른 장점은 likeItemName() , maxPrice() 를 다른 쿼리를 작성할 때 재사용 할 수 있다

 

 

 

 

 

 

 


https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-2/dashboard

 

스프링 DB 2편 - 데이터 접근 활용 기술 - 인프런 | 강의

백엔드 개발에 필요한 DB 데이터 접근 기술을 활용하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., 백엔드 개발자

www.inflearn.com

https://ittrue.tistory.com/292

 

[JPA] QueryDSL 소개 및 장점

QueryDSL이란? QueryDSL은 하이버네이트 쿼리 언어(HQL: Hibernate Query Language)의 쿼리를 타입에 안전하게 생성 및 관리해주는 프레임워크이다. QueryDSL은 정적 타입을 이용하여 SQL과 같은 쿼리를 생성할

ittrue.tistory.com