-
카테고리
-
세부 분야
백엔드
-
해결 여부
해결됨
강사님 where 다중 파라미터를 이용한 동적 쿼리 사용에 대한 질문입니다.
20.11.22 00:18 작성 조회수 3.34k
27
강사님 강의 잘 보고 있습니다.
다름아니라, where 다중 파라미터를 사용하면 가독성이 높아지는 건 이해했습니다.
영상 8분경의 메소드
private BooleanExpression allEq(String userNameCond, Integer ageCond) {
return userNameEq(userNameCond).and(ageEq(ageCond));
}
에 대한 질문인데요 문제는 userNameCond가 null일 경우 userNameEq가 null을 반환하기 때문에 BooleanExpression으로 체이닝을 할 수가 없는데
혹시 이럴경우 null 걱정없이 강제로 체이닝 하는 방법은 없을까요?
BooleanExpression을 체이닝 하려고 해봤는데 추상클래스라 객체 생성이 안되네요
답변을 작성해보세요.
19
김영한
지식공유자2020.11.23
갓다귀갓장국님 선물입니다. ㅋㅋㅋ 투척
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을 공부하시면 이렇게 코드를 더 줄일 수 도 있습니다.
좋은 하루 되세요^^
dhdh9224@gmail.com
2021.08.07
강사님 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);
7
김영한
지식공유자2020.11.22
안녕하세요. 갓다귀갓장국님 이제 끝이 보이는군요^^
다음 코드를 보시면 대략 어떻게 해야할지 감이 잡히실거에요.
@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));
}
}
감사합니다.
6
김영한
지식공유자2020.11.28
공부공부님 아쉽게도 ExpressionUtils.allOf를 사용해도 null처리는 따로 해주어야 합니다^^
다음 코드를 보시면 이해가 되실꺼에요.
return ExpressionUtils.allOf(member.age.eq(age), member.roleName.eq(roleName));
이렇게 풀어보면 member.age.eq(null) 이렇게 되는데, eq() 자체가 null을 받으면 예외가 발생합니다.
감사합니다.
4
김영한
지식공유자2021.01.21
안녕하세요. 참치캔님 하나씩 답변 달아드릴게요.
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의 구현과 관련된 곳에 두는 것이 좋습니다.
감사합니다.
3
2
1
단무지
2021.01.16
강사님 질문을 보다가 저도 궁금한게 생겨서 질문남겨봅니다..!
1. nullSafeBuilder 메서드는 다른 메서드처럼 private 인스턴스로 안 만드시고, public static메서드로 설계하셨는데 이 부분에 대해서 혹시 설명을 들어볼 수 있을까요??!
2. nullSafeBuilder 메서드에서catch로 NPE가 아닌 IllegalArgumentException 을 잡으신 이유에 대해서 궁금합니다!
혹시 만약 nullSafeBuilder 메서드를 다른 클래스에서도 사용하려고 만드신거면 nullSafeBuilder 메서드는 어느 클래스나, 패키지에 귀속되는 게 맞을까요..??!!
감사합니다!
0
0
공부공부
2020.11.28
아래처럼 하면 Predicate를 반환해도 되고, null 처리도 될거같네요.
import com.querydsl.core.types.ExpressionUtils;
private Predicate ageAndRoleEq(Integer age, String role) {
return ExpressionUtils.allOf(ageEq(age), roleEq(role));
}
답변 9