동적 쿼리를 해결하는 두번째 방법인 Where 다중 파라미터 사용에 대해 알아보겠습니다.
코드가 정말 깔끔해져서 실무에서 많이 사용합니다.
검색조건에 따라서 username이 member1 이거나 age가 10살인 사람을 찾고 싶다고 가정해봅시다.
import com.querydsl.core.types.dsl.BooleanExpression;
@BeforeEach
void setUp() {
queryFactory = new JPAQueryFactory(em);
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
em.persist(teamA);
em.persist(teamB);
Member member1 = new Member("member1", 10, teamA);
Member member2 = new Member("member2", 20, teamA);
Member member3 = new Member("member3", 30, teamB);
Member member4 = new Member("member4", 40, teamB);
em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
}
@DisplayName("WhereParam")
@Test
void dynamicQuery_WhereParam() {
String usernameParam = "member1";
Integer ageParam = null;
List<Member> result = searchMember2(usernameParam, ageParam);
assertThat(result.size()).isEqualTo(1);
}
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(member)
.where(usernameEq(usernameCond), ageEq(ageCond))
.fetch();
}
//...3
private Predicate usernameEq(String usernameCond) {
//...1
if (usernameCond == null) {
return null;
}
return member.username.eq(usernameCond);
}
//...3
private BooleanExpression ageEq(Integer ageCond) {
if (ageCond == null) {
return null;
}
return member.age.eq(ageCond);
}
where 조건에 null 값은 무시됩니다.
usernameCond 이 null 이면 null 을 반환합니다.
그렇다면 where(null, …) 가 되겠죠.
where 에서 null 값이 들어오면 무시가 됩니다. 아무역할도 하지 않아서 동적쿼리가 만들어집니다.
메서드들은 삼항연산자로 간단하게 리팩토링 할 수 있겠죠.
private Predicate usernameEq(String usernameCond) {
return usernameCond!= null ? member.username.eq(usernameCond) : null;
}
private Predicate ageEq(Integer ageCond) {
return ageCond != null ? member.age.eq(ageCond) : null;
}
참고로 삼항연산자는 긍정을 먼저 사용하는게 낫죠.
Predicate 보다는 BooleanExpression 을 사용하는게 낫습니다.
메서드를 조합해서 사용하려면 BooleanExpression 를 사용해야하기 때문입니다. → 자세히
어차피 BooleanExpression 는 Predicate 를 상속받고 있습니다.
실행해서 쿼리를 확인해봅시다.
ageParam 에 null 을 넣었으니 조건이 빠졌습니다. 동적 쿼리가 작동했다는 것을 알 수 있습니다.
이렇게 메서드를 따로 만들면 귀찮다고 생각할 수 있는데요, 사실 개발할 때 메서드 명으로 동작을 유추하는 경우가 많습니다. usernameEq 은 username 과 같다는게 직관적으로 보여서 동적쿼리가 머리속에서 정리가 되죠.