반응형
해당 글은 김영한 님의 querydsl을 수강하며 정리하려고 적는 포스팅입니다.
서론
JPA를 사용하다 보면 동적 쿼리를 작성해야 할 때가 있다.
querydsl은 동적 쿼리를 해결하는 두 가지 방식을 제공하고 있다.
동적 쿼리를 해결하는 두 가지 방식
- BooleanBuilder
- Where 다중 파라미터 사용
1. BooleanBuilder
@Test
public void dynamicQuery_BooleanBuilder() {
String usernameParam = "member1";
Integer ageParam = null;
List<Member> result = searchMember1(usernameParam, ageParam);
assertThat(result.size()).isEqualTo(1);
}
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();
}
---------------------------------------------------------------------------
2023-01-13T16:23:09.451+09:00 DEBUG 17488 --- [ main] org.hibernate.SQL :
/* select
member1
from
Member member1
where
member1.username = ?1 */ select
m1_0.member_id,
m1_0.age,
m1_0.team_id,
m1_0.username
from
member m1_0
where
m1_0.username=?
값이 필수로 넘어 온다고 가정한다면 아래처럼 BooleanBuilder의 생성자에 필수 param을 넣어주면 된다.
- BooleanBuilder builder = new BooleanBuilder(member.username.eq(usernameCond));
2. Where 다중 파라미터 사용
@Test
public 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))
//.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));
}
- where 조건에 응답 값으로 null이 들어가면 무시한다. (동적 쿼리가 만들어진다.)
- 메서드를 다른 쿼리에도 재활용 가능하다.
- 쿼리 자체의 가독성이 높아져서 1번 방법인 BooleanBuilder 보다 좋다
- 조합도 가능하다
조합 가능
private BooleanExpression allEq(String usernameCond, Integer ageCond) {
return usernameEq(usernameCond).and(ageEq(ageCond));
}
// 조합 예시 - 광고 상태 isValid, 날자가 In => isServicable라는 서비스 생성
// private BooleanExpression isServicable(String usernameCond, Integer ageCond) {
// return isValid(usernameCond).and(DateBwtweenIn(ageCond));
// }
- 대신 null 체크는 주의해서 처리해 주어야 한다.
- BooleanExpression로 타입을 사용해야 조합이 가능하다.
- Predicate 타입으로 사용하면 조합이 불가능하다.
반응형
'Java' 카테고리의 다른 글
[JPA] SQL function 호출하기 (0) | 2023.01.16 |
---|---|
[JPA] Querydsl 수정, 삭제 벌크 연산 (0) | 2023.01.15 |
[JPA] 프로젝션과 결과 반환 - @QueryProjection (0) | 2023.01.13 |
[JPA] 프로젝션과 결과 반환 - DTO 조회 (0) | 2023.01.13 |
[JPA] 프로젝션과 결과 반환 - 기본 (0) | 2023.01.13 |