-
Querydsl의 동적 쿼리JPA/Querydsl 2023. 8. 13. 15:26
동적 쿼리를 해결하는 방법
- 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번째 방식으로 했을 때에는 조건들을 따로 메서드로 빼놓기 때문에 재사용할 때도 훨씬 편하다는 장점이 있다.
'JPA > Querydsl' 카테고리의 다른 글
Querydls 동적 쿼리 활용 (0) 2023.08.13 Querydsl의 수정, 삭제 쿼리 (0) 2023.08.13 Dto로 프로젝션 결과 반환 (0) 2023.08.13 Querydsl - Case 문 (0) 2023.08.13 Querydsl - 서브 쿼리 (0) 2023.08.13