-
Querydsl - where절을 이용한 동적 쿼리Spring/Querydsl 2022. 3. 25. 14:36728x90반응형
where절을 이용한 동적 쿼리
where절을 이용하여 동적 쿼리를 처리할 수 있다. where 조건에서 null 값이 들어오면 값은 무시되고 쿼리가 생성된다. 이러한 특성 때문에 다른 쿼리에서도 재활용이 가능한 장점이 있고, 또한 쿼리 자체의 가독성이 높아진다. BooleanBuilder보다 사용하기 편하므로 이 방법을 권장한다.
@Test public void dynamicQuery_WhereParam() { String usernameParam = "member1"; Integer ageParam = 10; 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(); } 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; }
/* select member1 from Member member1 where member1.username = ?1 and member1.age = ?2 */ select member0_.member_id as member_id1_1_, member0_.age as age2_1_, member0_.team_id as team_id4_1_, member0_.username as username3_1_ from member member0_ where member0_.username=? and member0_.age=?
위에서 코드를 보면 usernameEq과 ageEq 메서드를 이용하였다. 이 메서드들은 충분히 다른 쿼리에서도 충분히 쓸 수 있기 때문에 재사용성이 높아진다. 또한 생성한 메서드를 이용한 메서드를 만들 수 있다. 다음 예시를 보자.
private BooleanExpression allEq(String usernameCond, Integer ageCond) { return usernameEq(usernameCond).and(ageEq(ageCond)); }
이처럼 usernameEq 메서드와 ageEq 메서드를 다음과 같이 재사용하여 하나의 다른 메서드를 생성할 수 있다.
참고
위에 allEq 메서드는 null 체크를 하지 않았지만
필수적으로 null 체크를 해줘야 한다.@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)); } }
자바 8을 이용하면 코드를 줄여줄 수 있다.
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(); } }
728x90반응형'Spring > Querydsl' 카테고리의 다른 글
Querydsl - Repository에서 Querydsl 사용하기 (0) 2022.03.26 Querydsl - 수정, 삭제 벌크 연산 (0) 2022.03.25 Querydsl - BooleanBuilder 이용한 동적 쿼리 (0) 2022.03.25 Querydsl - DTO로 조회하기 (0) 2022.03.25 Querydsl - 프로젝션에 따른 결과 반환 (0) 2022.03.25