• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

querydsl 동적쿼리 where문에 여러 메서드 사용 null처리 어떤식으로 하는게 좋을까요?

23.03.22 03:25 작성 조회수 1.96k

0

private List<Member> searchMember2(String usernameCond, Integer ageCond) {
    return queryFactory
            .selectFrom(member)
            .where(allEq(usernameCond,ageCond))//메서드를 만들어서 한번에 처리도 가능, 조립가능!!
            .fetch();
}
private BooleanExpression usernameEq(String usernameCond) {
    return usernameCond != null ? member.username.eq(usernameCond) : null;
}
private BooleanExpression ageEq(Integer ageCond) {
    return ageCond != null ? member.age.eq(ageCond) : null;
}
private BooleanExpression allEq(String usernameCond, Integer ageCond){
    return usernameEq(usernameCond).and(ageEq(ageCond));
}

강사의 내용에서 알려주신 코드중 usernameEq메서드의 return값이 null일 때 어떤식으로 처리하는 것이 좋을까요???

BooleanBuilder객체에 함수를 체이닝 할까 고민해봤지만 체이닝이 잘안되기도하고, BooleanBuilder를 사용할꺼면 usernameEq, ageEq와 같은 메서드를 만드는 의미가 없다고 생각아 합니다..... 좋은 방법있다면 알려주시면 감사하겠습니다.

답변 1

답변을 작성해보세요.

1

y2gcoder님의 프로필

y2gcoder

2023.03.22

안녕하세요, 백엔드 개발자 취준생 님. 공식 서포터즈 y2gcoder 입니다.

해당 질문에 대한
링크가 있어서 참고해보시겠습니까? 들어가셔서 쭉 타고 들어가시면 될 것 같습니다:)

감사합니다.

감사합니다!딱 원했던 해결책입니다!정말 감사합니다!

y2gcoder님의 프로필

y2gcoder

2023.03.22

파이팅입니다!

@Test
public void dynamicQuery_WhereParam(){
    String usernameParam = null;
    Integer ageParam = 10;

    List<Member> result = searchMember2(usernameParam, ageParam);
    for (Member member1 : result) {
        System.out.println("member1 = " + member1);
    }
    assertThat(result.size()).isEqualTo(1);
}
private List<Member> searchMember2(String[] usernameCond, Integer ageCond) {
    return queryFactory
            .selectFrom(member)
            .where(ageEqNullSafe(ageCond).and(usernameInNullSafe(usernameCond)))
            .fetch();
}
private BooleanBuilder ageEqNullSafe(Integer age) {
    return nullSafeBuilder(() -> member.age.eq(age));
}

private BooleanBuilder usernameInNullSafe(String[] username){
    return nullSafeBuilder(()->member.username.in(username));
}

nullsafeBuilder를 이용해서 이것저것 테스트 중인데 usernameInNullSafe메서드를 보면 in절에 ArrayList, String[] 등의 iterable한 객체들이 들어가면 아래와같은 에러가 발생하더라고요ㅠㅠㅠㅠ

java.lang.NullPointerException

at com.querydsl.core.types.dsl.SimpleExpression.in(SimpleExpression.java:205)

그래서 혹시 in절에 String타입으로 넣고 null을 넣어도 에러가 뜨나 확인해보려고 아래와 같이 작성하니 잘작동합니다.ㅠㅠㅠㅠㅠ

@Test
public void dynamicQuery_WhereParam(){
    String usernameParam = null;
    Integer ageParam = 10;

    List<Member> result = searchMember2(usernameParam, ageParam);
    for (Member member1 : result) {
        System.out.println("member1 = " + member1);
    }
    assertThat(result.size()).isEqualTo(1);
}

private List<Member> searchMember2(String usernameCond, Integer ageCond) {
    return queryFactory
            .selectFrom(member)
            .where(ageEqNullSafe(ageCond).and(usernameInNullSafe(usernameCond)))
            .fetch();
}
private BooleanBuilder ageEqNullSafe(Integer age) {
    return nullSafeBuilder(() -> member.age.eq(age));
}

private BooleanBuilder usernameInNullSafe(String username){
    return nullSafeBuilder(()->member.username.in(username));
}

like문은 어떤가 확인해보기 위해 아래의 코드와같이 like문에 null을 입력하니 iterable객체가 아니여도 에러가 발생하더라고요ㅠㅠㅠㅠ

@Test
public void dynamicQuery_WhereParam(){
    String usernameParam = null;
    Integer ageParam = 10;

    List<Member> result = searchMember2(usernameParam, ageParam);
    for (Member member1 : result) {
        System.out.println("member1 = " + member1);
    }
    assertThat(result.size()).isEqualTo(1);
}


private List<Member> searchMember2(String usernameCond, Integer ageCond) {
    return queryFactory
            .selectFrom(member)
            .where(ageEqNullSafe(ageCond).and(usernameLike(usernameCond)))
            .fetch();
}
private BooleanBuilder usernameLike(String username){
    return nullSafeBuilder(()->member.username.like(username));
}
private BooleanBuilder ageEqNullSafe(Integer age) {
    return nullSafeBuilder(() -> member.age.eq(age));
}

in절이나 like절에 받아들일 수 없는 파라미터가 존재하는 것 같은데 이런경우에는 어쩔수없이 BooleanBuilder를 사용해야 하는 건가요? 아님 제가 코드를 잘못 작성하고 있는 걸까요...?

y2gcoder님의 프로필

y2gcoder

2023.03.22

혹시 and 조건만 있다면 where() 안에 , 로 추가하는 것을 어떻게 생각하십니까?
그렇게 하면 null 조건에 대해 걱정할 필요가 없을 것 같습니다.

백엔드 개발자 취준생님의 코드를 보다보니 혹시 하는 생각이 들어서 질문드립니다 :)

where절에 or조건도 사용해야해서 or조건들만 BooleanBuilder를 객체에 조건들을 체이닝하고, 나머지 and조건들은 , 로 코드를 넣는식으로 해결하였습니다! 하지만 like 도는 in절의 파라미터자체에 null을 넣지못하는 상황이여서 nullSafeBuiler를 사용하지 못하는 아쉬움이 있습니다ㅠㅠㅠ

private BooleanExpression nameLike(String writer) {
        return StringUtils.hasText(writer) ? article.member.name.contains(writer) : null;
    }

 위와 같이 원래 강의에서 구현하던 식으로 writer자체를 먼저 null처리를 해주면서 구현하였습니다

y2gcoder님의 프로필

y2gcoder

2023.03.26

멋있습니다 ㅎㅎ 파이팅입니다!