inflearn logo
강의

Khóa học

Chia sẻ kiến thức

Trong thực tế! Truy vấn

Truy vấn động - Sử dụng nhiều tham số trong điều kiện Where

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

Đã giải quyết

5162

godjangkook

24 câu hỏi đã được viết

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

Câu trả lời 9

22

yh

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

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

deokhwan

강사님 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

yh

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

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

8

yh

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

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

@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

yh

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

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

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

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

감사합니다.

5

yh

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

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

godjangkook

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

3

godjangkook

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

2

tlfanfvk7878

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

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

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

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

감사합니다!

0

tlfanfvk7878

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

0

spaceeducat4638

아래처럼 하면 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

87

2

querydsl 오픈소스에 대한 질문

0

72

1

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

0

109

1

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

0

317

2

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

1

70

1

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

0

160

1

querydsl sum() 메서드 없어요.

0

158

2

build 디렉터리 생성

0

136

2

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

0

114

2

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

0

90

1

오타 제보 드립니다.

0

72

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

158

2

count 쿼리 관련 질문입니다!

0

75

1

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

0

89

1

답변부탁드리겠습니다.

0

89

2

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

0

65

1

중급문법 벌크연산에서

0

81

2