Querydsl의 동적 쿼리
동적 쿼리를 해결하는 방법
- BooleanBuilder
- Where 다중 파라미터 사용
1. BooleanBuilder
private List<Member> searchMember1(String usernameCond, Integer ageCond) {
BooleanBuilder builder = new BooleanBuilder();
if(usernameCond != null) {
builder.and(member.username.eq(usernameCond));
}
if (ageCond != null) {
builder.and(member.age.eq(ageCond));
}
return queryFactory
.selectFrom(member)
.where(builder)
.fetch();
}
BooleanBuilder를 생성해서 builder에 조건을 걸어둔다. 위에서는 username이나 age가 null이 아닐 때 그와 같은 조건만 select하는 쿼리를 만들어서 반환을 해줬다.
@Test
public void dynamicQuery_BooleanBuilder() {
String usernameParam = "member1";
Integer ageParam = 10;
List<Member> result = searchMember1(usernameParam, ageParam);
assertThat(result.size()).isEqualTo(1);
}
테스트에서 searchMember1()을 사용한 결과 member1이라는 회원 한 명만 조회했다. usernameParam과 ageParam을 사용자에게 입력받게 하면 웹 상에서 검색을 할 수 있을 것이다.
초기값 넣기
BooleanBuilder builder = new BooleanBuilder(member.username.eq(usernameCond));
생성자를 만들 때 이렇게 넣어주면 username은 무조건 넣어야한다는 규칙을 만드는 것이다.
2. Where 다중 파라미터 사용
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(member)
.where(usernameEq(usernameCond), ageEq(ageCond))
.fetch();
}
where문에서 쿼리의 조건을 다 끝내는 것이다. 이 때에는 where문에 있는 메서드들을 정의해줘야 한다.
private Predicate usernameEq(String usernameCond) {
if (usernameCond == null) {
return null; // null을 반환하면 where절이 null이라 무시되어서 name에 조건을 걸지 않음
}
return member.username.eq(usernameCond);
}
private Predicate ageEq(Integer ageCond) {
return ageCond != null ? member.age.eq(ageCond) : null; // 삼항 연산자 사용
}
조건에 해당하는 값들이 null이면 where절에 member.age.eq(ageCond)와 같은 식으로 조건을 걸어주고 아니면 null을 반환한다.
이름의 조건이 null이어서 null을 반환한다고 가정하자 Querydsl의 쿼리의 where절에서는 where(null, member.age.eq(ageCond)가 될 것인데 null이 들어가면 조건을 걸지 않으므로 이름으로는 조건을 걸지 않고 나이로만 select를 하는 것이다.
@Test
public void dynamicQuery_WhereParam() {
String usernameParam = "member1";
Integer ageParam = 10;
List<Member> result = searchMember2(usernameParam, ageParam);
assertThat(result.size()).isEqualTo(1);
}
테스트는 1번 방식과 동일한 코드이다. 메서드만 searchMember2()로 변경해주었다.
조건 묶어서도 가능
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));
}
이럴 때에는 BooleanExperssion으로 반환값을 바꿔줘야하며 null 처리를 특별히 신경써 줘야한다.
Querydsl을 사용하면 자바 코드로 쿼리를 날리는 것이기 때문에 동적 쿼리를 작성할 때 훨씬 편리해진다. 또한 2번째 방식으로 했을 때에는 조건들을 따로 메서드로 빼놓기 때문에 재사용할 때도 훨씬 편하다는 장점이 있다.