2023년 1월 1일
08:00 AM
Buffering ...

최근 글 👑

[스프링] booleanExpresstion 사용법 QueryDSL란 무엇인가?

2023. 6. 20. 18:42ㆍ[스프링 DB]/QueryDSL

queryDSL란? QueryDSL 설정방법, 설치 , 의존성 추가 (tistory.com)

 

queryDSL란? QueryDSL 설정방법, 설치 , 의존성 추가

[QueryDSL이란?] QueryDSL은 하이버네이트 쿼리 (HQL : Hibernate Query Language)의 쿼리를 타입에 안전하게 생성 및 관리 해주는 언어이다. 즉 스프링에서는 동적 쿼리를 작성할 때 정말 까다롭지 않을 수 없

thaud153.tistory.com

 

 

QueryDSL의 사용방법과 QueryDSL이 무엇인지는 여기를 참고하길 바란다.

 

 

[JpaQueryFactory]

 

QueryDSL을 사용하기전에 우리는 JpaQueryFactory로 Query를 작성해야 한다.

 

List<Item> fetch = factory.selectFrom(item)
        .from(item)
        .where(builder)
        .fetch();

 

 

기본적으로 QueryDSL은 이러한 양식으로 작성되며 이러한 메서드를 가지고 있는 클래스가 바로 JpaQueryFactory이다.

 

 

private final JPAQueryFactory factory;

 

 

JpaQueryFactory는 QueryDSL의 의존성을 추가하면 생기는 클래스이며 JpaQueryFactory를 통해 쿼리를 작성하게 된다.

 

 

[JpaQueryFactory 사용방법]

 

JpaQueryFactory는 기본적으로 스프링이 자동으로 주입 해주지 않기 때문에 

개발자 스스로가 등록해야 한다.

 

등록방법은 두 가지가 있다.

 

▶ Bean으로 등록

 

▶ 생성자를 통한 방법

 

 

[Bean으로 등록방법]

 

Bean으로에 등록방법을 알아보자.

 

 

@Bean
public JPAQueryFactory factory(){
        return new JPAQueryFactory(manager);
    }

 

 

@Bean으로 등록시 JPAQueryFactory에 들어갈 파라미터는 EnityManager를 넣어줘야 한다.

물론 EntityManager를 사용하기 위해선 DataSource의 저장정보를 반드시 넣어줘야만 한다.

 

 

DataSource의 정보를 넣는 방법은 여러가지가 있지만 

나의 경우는 스프링이 제공하는 프로퍼티스에 이 정보들을 넣겠다.

 

 

 

이렇게 DataSource의 정보를 넣는다면

스프링이 EntityManager와 DataSource는

자동으로 주입 해주기 때문에 JpaQueryFactory에 EntityManager만 넣는다면 설정은 완료 된다.

 

 

 

 

Config의 정보이다. 

 

 

 

 

 

[생성자로 등록방법]

 

 

생성자로의 등록방법은 Bean과 똑같이 적용시켜주면 된다.

 

 

 

 

 

[BooleanExpresstion의 사용]

 

QueryDSL을 사용하면 BooleanBuilder와 BooleanExpresstion 중 사용하게 되는데

나의 경우는  BooleanExpresstion가 더 편한 것 같다. 

실제로도 많은 개발자들이  BooleanExpresstion 를 더 많이 사용하는 것 같다.

 

사용방법은 

 

JpaQueryFactory를 본다면 이러한 메서드들이 존재한다.

 

 

 

 

기본적으로 이러한 메서드들을 제공하는데 QueryDSL을 사용하는 양식은 이렇다

 

 

factory.selectFrom(item) //Q 객체가 들어감
        .where(ItemName_eq(cond)) //QueryDSL통해 Where절 조건을 완성시켜야 함.
        .fetch();

 

 SelectFrom(Q객체)

where(조건절)

fectch()로 이루어져있다.

 

우리가 만들어야 하는 것은 where의 조건절인데

이 조건절을 BooleanExpresstion으로 만드는 것 이다.

 

 

나의 경우는 동적 쿼리로 이러한 것을 찾을 것 이다.

 

[조건]

 

검색 조건 -> 아이템 이름과 가격이 들어감.

 

아이템 이름만 입력시 -> 해당 아이템과 관련된 아이템이 나오게 함 

 

가격 입력시 -> 10,000원을 입력 할 시 10,000보다 작은 아이템들이 나오게 함

 

Null이나 공백 입력시 -> 모든 아이템들이 나오게 함 .

 

 

이제 이러한 동적쿼리를 작성해보자.

 

 

 

 

BooleanExpression likeItemName(String itemName){
    return StringUtils.hasText(itemName) ? item.itemName.like("%d"+itemName+"%d") : null;
}

 

 

BooleanExpresstion으로 사용한다면 이렇게 작성해야 한다.

 

BooleanExpresstion 이러한 특성을 가지고 있다.

 

▶ 조건이 맞지 않을 경우 null반환 시 where절에서 적용을 시키지 않음.

 

▶조건이 한개이고 이 조건이 null이라면 where도 삭제 시킨다.

 

 

이게 무슨뜻이나면

 

예를 들어

 

select * from item where itemName = "상품A";

 

이러한 쿼리문이 있다고 치자.

 

하지만 BooleanExpresstion으로 조건을 비교한 후 조건에 null이 들어간다면 

 

select * from item;

 

이런식으로 조건이 한개 일때는 where 절과 조건절을 아예 빼버리고 이렇게 전체 조회를 하게 된다.

 

만약 null이 아니라면 우리가 설정한 값들의 조건을 반환 시킨다.

주의 할 점은 Q객체로 메서드를 작성해야 한다.

 

기본적으로 QItem은 static 클래스임으로 Q객체가 생성됨과 동시에

쿼리에 있는 메서드를 사용 할 수 있게 되는 것이다. 

즉 BooleanExpresstion을 작성시에는 

 

QItem.item.itemName.like("%d"+itemName+"%d");

 

이렇게 작성해주어야 한다.

 

 

 

나의 경우는 아이템 이름과 , 가격을 설정해야 하기 때문에 조건을 두 개를 넣어야 한다.

 

 

 

아까와 마찬가지로 삼항연산자를 적용하여 더 깔끔한 코드로 작성 할 수 있다.

 

 

이러한 두 개의 메서드들을 

 

 

factory.selectFrom(item)
        .where(likeItemName(cond.getItemName()),lowPrice(cond.getMaxPrice()))
        .fetch();

 

 

where절에 우리가 만든 메서드들을 넣어주면 된다.

 

이렇게 where절에 우리가 만든 메서드들을 넣는다면 

 

이런식으로 적용 될 것 이다.

 

select * from item where itemName = cond.itemName and price = cond.getMaxPrice;

 

이러한 쿼리가 작성 되는데 여기서 우리가 만든 메서드들이 null일 경우

이러한 조건들이 사라지게 된다.

 

예를들어

우리가 만든 메서드 lowPrice가 null일 경우는

 

 

select * from item where itemName = cond.itemName;

 

이런식으로 적용 될 것이다.

 

만약 둘 다 null일 경우는 이제 다들 이해하기 쉬울 것 이다.

 

select * from item;

 

이런식으로 동적쿼리가 오기 때문에 정말 편하게 동적쿼리를 작성할 수 있다.

 

 

한번 되는지 안되는지 실행 해보도록 하자.

 

 

이러한 조건으로 검색했을때 잘 나오는걸 확인 할 수 있다.

 

 

 

 

아무것도 안넣었을 때는 null임으로 전체 조회를 하게 끔 했으니 정상적으로 작동이 잘 되는 걸 확인 할 수 있다.

 

 

 

[정리]

 

즉 QueryDsl란 스프링도 해결하지 못했던 동적쿼리를 매우 쉽게 사용할 수 있게 해주며

Jpa와 QueryDsl을 함께 사용시 엄청난 효율을 끌어 낼 수 있다.

또한 QueryDSL은 Q객체라는 것을 사용하는데 이 Q객체를 기반으로

QueryDsl을 작성할 수 있다.