해결된 질문
작성
·
4.5K
28
강사님 강의 잘 보고 있습니다.
다름아니라, where 다중 파라미터를 사용하면 가독성이 높아지는 건 이해했습니다.
영상 8분경의 메소드
private BooleanExpression allEq(String userNameCond, Integer ageCond) {
return userNameEq(userNameCond).and(ageEq(ageCond));
}
에 대한 질문인데요 문제는 userNameCond가 null일 경우 userNameEq가 null을 반환하기 때문에 BooleanExpression으로 체이닝을 할 수가 없는데
혹시 이럴경우 null 걱정없이 강제로 체이닝 하는 방법은 없을까요?
BooleanExpression을 체이닝 하려고 해봤는데 추상클래스라 객체 생성이 안되네요
답변 9
21
갓다귀갓장국님 선물입니다. ㅋㅋㅋ 투척
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을 공부하시면 이렇게 코드를 더 줄일 수 도 있습니다.
좋은 하루 되세요^^
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
2
강사님 질문을 보다가 저도 궁금한게 생겨서 질문남겨봅니다..!
1. nullSafeBuilder 메서드는 다른 메서드처럼 private 인스턴스로 안 만드시고, public static메서드로 설계하셨는데 이 부분에 대해서 혹시 설명을 들어볼 수 있을까요??!
2. nullSafeBuilder 메서드에서catch로 NPE가 아닌 IllegalArgumentException 을 잡으신 이유에 대해서 궁금합니다!
혹시 만약 nullSafeBuilder 메서드를 다른 클래스에서도 사용하려고 만드신거면 nullSafeBuilder 메서드는 어느 클래스나, 패키지에 귀속되는 게 맞을까요..??!!
감사합니다!
0
0
아래처럼 하면 Predicate를 반환해도 되고, null 처리도 될거같네요.
import com.querydsl.core.types.ExpressionUtils;
private Predicate ageAndRoleEq(Integer age, String role) {
return ExpressionUtils.allOf(ageEq(age), roleEq(role));
}
강사님 nullSafeBuilder 부분도 람다로 고쳐보고싶은데!..
이렇게하면 익셉션이뜨더군요,,
그래서 이렇게도 해보았는데 똑같이 안되더군요 .. 람다로 어떻게 풀수있을까요?..