inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

실전! Querydsl

동적 쿼리 - Where 다중 파라미터 사용

강사님 where 다중 파라미터를 이용한 동적 쿼리 사용에 대한 질문입니다.

해결된 질문

5161

갓다귀갓장국

작성한 질문수 24

28

강사님 강의 잘 보고 있습니다. 

다름아니라, where 다중 파라미터를 사용하면 가독성이 높아지는 건 이해했습니다.

영상 8분경의 메소드

    private BooleanExpression allEq(String userNameCond, Integer ageCond) {

        return userNameEq(userNameCond).and(ageEq(ageCond));

    }

에 대한 질문인데요 문제는 userNameCond가 null일 경우 userNameEq가 null을 반환하기 때문에 BooleanExpression으로 체이닝을 할 수가 없는데

혹시 이럴경우 null 걱정없이 강제로 체이닝 하는 방법은 없을까요?

BooleanExpression을 체이닝 하려고 해봤는데 추상클래스라 객체 생성이 안되네요

java JPA

답변 9

22

김영한

갓다귀갓장국님 선물입니다. ㅋㅋㅋ 투척

private BooleanBuilder ageEq(Integer age) {
return nullSafeBuilder(() -> member.age.eq(age));
}

private BooleanBuilder roleEq(String roleName) {
return nullSafeBuilder(() -> member.roleName.eq(roleName));
}

public static BooleanBuilder nullSafeBuilder(Supplier<BooleanExpression> f) {
try {
return new BooleanBuilder(f.get());
} catch (IllegalArgumentException e) {
return new BooleanBuilder();
}
}

자바 8을 공부하시면 이렇게 코드를 더 줄일 수 도 있습니다.

좋은 하루 되세요^^

0

더콰니

강사님 nullSafeBuilder 부분도 람다로 고쳐보고싶은데!..

 public static BooleanBuilder NullSafeBuilders(Supplier<BooleanExpression> o ){
       return Optional.ofNullable(o.get()).map(BooleanBuilder::new).orElseGet(BooleanBuilder::new);
    }

이렇게하면 익셉션이뜨더군요,,

 

그래서  이렇게도 해보았는데 똑같이 안되더군요 .. 람다로 어떻게 풀수있을까요?..

return Optional.ofNullable(o.get()).map(BooleanBuilder::new).orElseThrow(IllegalArgumentException::new);

2

김영한

이 코드를 람다로 풀 이유를 잘 모르겠습니다^^

혹시 아시는 분 있으면 답변 부탁드립니다.

8

김영한

안녕하세요. 갓다귀갓장국님 이제 끝이 보이는군요^^

다음 코드를 보시면 대략 어떻게 해야할지 감이 잡히실거에요.

@DataJpaTest
public class DynamicQueryTest {

JPAQueryFactory queryFactory;
@Autowired
EntityManager em;

@BeforeEach
void init() {
queryFactory = new JPAQueryFactory(em);

em.persist(new Member("userA", 10, "ROLE_MASTER"));
em.persist(new Member("userB", 20, "ROLE_ADMIN"));
em.persist(new Member("userC", 30, "ROLE_USER"));
}

@Test
void dynamicQuery() {

// Integer age = 10;
// String role = "ROLE_MASTER";
Integer age = null;
String role = null;

List<Member> result = queryFactory
.selectFrom(member)
.where(ageAndRoleEq(age, role))
.fetch();

System.out.println("result = " + result);

}

private BooleanBuilder ageAndRoleEq(Integer age, String role) {
return ageEq(age).and(roleEq(role));
}

private BooleanBuilder ageEq(Integer age) {
if (age == null) {
return new BooleanBuilder();
} else {
return new BooleanBuilder(member.age.eq(age));
}
}

private BooleanBuilder roleEq(String roleName) {
if (roleName == null) {
return new BooleanBuilder();
}
return new BooleanBuilder(member.roleName.eq(roleName));
}

}

감사합니다.

7

김영한

공부공부님 아쉽게도 ExpressionUtils.allOf를 사용해도 null처리는 따로 해주어야 합니다^^

다음 코드를 보시면 이해가 되실꺼에요.

return ExpressionUtils.allOf(member.age.eq(age), member.roleName.eq(roleName));

이렇게 풀어보면 member.age.eq(null) 이렇게 되는데, eq() 자체가 null을 받으면 예외가 발생합니다.

감사합니다.

5

김영한

안녕하세요. 참치캔님 하나씩 답변 달아드릴게요.

1. nullSafeBuilder 메서드는 다른 메서드처럼 private 인스턴스로 안 만드시고, public static메서드로 설계하셨는데 이 부분에 대해서 혹시 설명을 들어볼 수 있을까요??! 

-> 아~ 이것은 nullSafeBuilder를 공통으로 사용할 수 있는 유틸리티 클래스로 뽑아서 사용하라는 의미였습니다. 이 코드상에서는 private으로 하셔도 됩니다.

2. nullSafeBuilder 메서드에서catch로 NPE가 아닌 IllegalArgumentException 을 잡으신 이유에 대해서 궁금합니다!

Querydsl이 IllegalArgumentException을 호출합니다. 그래서 해당 예외를 잡았습니다.

public BooleanExpression eq(T right) {
if (right == null) {
throw new IllegalArgumentException("eq(null) is not allowed. Use isNull() instead");
} else {
return eq(ConstantImpl.create(right));
}

혹시 만약 nullSafeBuilder 메서드를 다른 클래스에서도 사용하려고 만드신거면 nullSafeBuilder 메서드는 어느 클래스나, 패키지에 귀속되는 게 맞을까요..??!!

-> 네 공통으로 적절하게 두시면 됩니다^^ 사실 계층을 명확하게 나눈다면 repository의 구현과 관련된 곳에 두는 것이 좋습니다.

감사합니다.

4

갓다귀갓장국

람다를 사용하니깐 더 깔끔해지네요. 생각지도 못한 선물 감사합니다  좋은 하루 보내세요^^

3

갓다귀갓장국

BooleanBuilder를 이렇게 활용하는 방식이 있었네요. 완전 응용이네요. 이방식 완전 좋네요 감사합니다^^

2

단무지

강사님 질문을 보다가 저도 궁금한게 생겨서 질문남겨봅니다..!

1. nullSafeBuilder 메서드는 다른 메서드처럼 private 인스턴스로 안 만드시고, public static메서드로 설계하셨는데 이 부분에 대해서 혹시 설명을 들어볼 수 있을까요??! 

2. nullSafeBuilder 메서드에서catch로 NPE가 아닌 IllegalArgumentException 을 잡으신 이유에 대해서 궁금합니다!

혹시 만약 nullSafeBuilder 메서드를 다른 클래스에서도 사용하려고 만드신거면 nullSafeBuilder 메서드는 어느 클래스나, 패키지에 귀속되는 게 맞을까요..??!!

감사합니다!

0

단무지

감사합니다. 아 저는 loe랑 goe로 실험했었는데 여기서는 NPE를 던졌는데 eq는 IllegalArgumentException 을 호출했네요..

0

공부공부

아래처럼 하면 Predicate를 반환해도 되고, null 처리도 될거같네요.

import com.querydsl.core.types.ExpressionUtils;    

private Predicate ageAndRoleEq(Integer age, String role) {
return ExpressionUtils.allOf(ageEq(age), roleEq(role));
}

SpringBoot 4.X에서의 Querydsl 설정

0

81

2

querydsl 오픈소스에 대한 질문

0

69

1

예제에서의 카운트 쿼리에서 join문과 where문은 필요없지 않나요?

0

108

1

Querydsl 6.X버전에 대해서 어떻게 생각하시나요?

0

316

2

여러 테이블 조인하여 통계치를 구하고자 할 때 어떤 방법이 더 효율적일까요

1

68

1

fetchResults()는 더이상 권장되지 않는다는데 맞나요?

0

159

1

querydsl sum() 메서드 없어요.

0

157

2

build 디렉터리 생성

0

135

2

자바 ORM 표준 JPA 프로그래밍 - 기본편 듣고 바로 학습해도 괜찮을까요?

0

113

2

현재 Querydsl에서 from절 서브쿼리를 지원하나요?

0

90

1

오타 제보 드립니다.

0

70

2

벌크 연산과 flush, clear

0

76

1

Run As Intellij 로 변경시 Q타입 import 불가

0

87

1

QHello import하기 문제 발생

0

147

2

등록된 함수 보는법(H2Dialect) 질문

0

68

2

5.0부터 Querydsl은 향후 fetchCount() , fetchResult() 를 지원하지 않기로 결정했다고 하는데 이에 맞는 강의

1

195

2

[환경설정 PDF 부트 3.0이후 설명 질문] build.gradle에 compileQuerydsl을 정의하지 않은 상태에서 Gradle->Tasks->other->compileQuerydsl을 클릭하라고 하는 이유가 무엇인가요??

1

200

1

querydsl 설정 문제

0

222

2

quey dsl 설정부분

0

157

2

count 쿼리 관련 질문입니다!

0

75

1

stringtemplate를 이용하여 where절 검색 방법 질문 드립니다.

0

89

1

답변부탁드리겠습니다.

0

89

2

(OrderSpecifier)관련 내용 어디있을가요

0

64

1

중급문법 벌크연산에서

0

81

2