GitHub

https://github.com/Choidongjun0830

Spring

[Spring DB2] 데이터 접근 기술 - Querydsl

gogi masidda 2024. 3. 25. 21:33

DSL

  • 도메인 + 특화 + 언어
  • 특정한 도메인에 초점을 맞춘 제한적인 표현력을 가진 컴퓨터 프로그래밍 언어
  • 특징 : 단순, 간결, 유창 

QueryDSL

  • 쿼리 + 도메인 + 특화 + 언어
  • 쿼리에 특화된 프로그래밍 언어
  • 단순, 간결, 유창
  • 다양한 저장소 쿼리 기능 통합 
  • 자바 코드로 쿼리를 작성할 수 있다. 
  • JPA, MongoDB, SQL 같은 기술들을 위해 type-safe SQL을 만드는 프레임 워크
  • SpringData프로젝트의 약점은 조회. Querydsl로 복잡한 조회 기능을 보완 가능(복잡한 쿼리, 동적 쿼리)
  • 컴파일 시점에 sql 오류를 잡아준다.
  • Querydsl은 스프링 예외 추상화를 해주지 않는다. 그래서 JPA에서처럼 @Repository에서 스프링 예외 추상화를 처리해준다. 

Querydsl 적용

@Repository
@Transactional
public class JpaItemRepositoryV3 implements ItemRepository {

    private final EntityManager em;
    private final JPAQueryFactory query; //JPAQueryFactory는 Querydsl꺼

    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)); //loe : 작거나 같다
        }

        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 maxPrice(Integer maxPrice) {
        if (maxPrice != null) {
            return item.price.loe(maxPrice); //loe : 작거나 같다
        }
        return null;
    }

    private BooleanExpression likeItemName(String itemName) {
        if(StringUtils.hasText(itemName)) {
            return item.itemName.like("%"+itemName+"%");
        }
        return null;
    }
}
  • Querydsl을 사용하려면 JPAQueryFactory가 필요하다. JPAQueryFactory는 JPQL을 사용하기 때문에 EntityManager가 필요하다.
  • save(), update(), findById()는 JPA가 제공하는 기본 기능을 사용한다.
  • findAllOld()
    • QItem.item은 static import해서 item으로 나오는 것이다.
    • Querydsl을 사용해서 동적 쿼리 문제를 해결
    • BooleanBuilder를 이용해서 원하는 where 조건들을 넣어주면 된다.
  • findAll()
    • where(A, B)에서 ,는 자동으로 and로 처리되고, where에 null이 들어오면 해당 조건은 무시된다.
    • 메서드 추출을 이용해서 maxPrice()와 likeItemName을 재사용할 수 있다.

 

 

728x90