굉장히 유용하니 잘 알아두도록 하자.
앞서 했던 BooleanBuilder와 같은 기능을 하지만 코드가 다르다.
아래 코드에서 where절에 null이 들어가면 어떻게 될까?
// QuerydslBasicTest
@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) {
if (usernameCond == null) {
return null;
}
return member.username.eq(usernameCond);
}
private Predicate ageEq(Integer ageCond) {
return null;
}
여기서 where에 null이 있는데 where null이 들어가게 되면
@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(null, ageEq(ageCond))
.fetch();
}
private Predicate usernameEq(String usernameCond) {
if (usernameCond == null) {
return null;
}
return member.username.eq(usernameCond);
}
private Predicate ageEq(Integer ageCond) {
return null;
}
}
where에 null이 들어가게 되면 무시가 된다. where는 and 조건인데 응답값이 null이면 null이 무시가 되는 것이다.
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(member)
.where(null, ageEq(ageCond))
.fetch();
}
삼항 연산자도 아래와 같이 줄 수 있다.
// 삼항연산자를 줄수가 있다.
// null이 아니면 ~조건 그게아니면 null
private Predicate usernameEq(String usernameCond) {
return usernameCond != null ? member.username.eq(usernameCond) : null;
}
테스트를 돌리면
@Test
public void dynamicQuery_WhereParam() {
String usernameParam = "member1";
Integer ageParam = 10;
List<Member> result = searchMember2(usernameParam, ageParam);
assertThat(result.size()).isEqualTo(1);
}
// member 조회하고 usernameEq하니까 ageEq보다.
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(member)
.where(usernameEq(usernameCond), ageEq(ageCond))
.fetch();
}
// 삼항연산자를 줄수가 있다.
// null이 아니면 ~조건 그게아니면 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;
}
// username와 age가 파라미터 바인딩 되어 넘어간다.
/* select
member1
from
Member member1
where
member1.username = ?1
and member1.age = ?2 */
select
member0_.id as 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=?
만약 ageParam이 null이 되면
where 절에서 null이 된다.
Integer ageParam = null;
.where(usernameEq(usernameCond), null)
@Test
public void dynamicQuery_WhereParam() {
String usernameParam = "member1";
Integer ageParam = null;
List<Member> result = searchMember2(usernameParam, ageParam);
assertThat(result.size()).isEqualTo(1);
}
// member 조회하고 usernameEq하니까 ageEq보다.
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(member)
.where(usernameEq(usernameCond), null)
.fetch();
}
// 삼항연산자를 줄수가 있다.
// null이 아니면 ~조건 그게아니면 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;
}
실행시키면 age가 없는 것을 확인할 수 있다.
/* select
member1
from
Member member1
where
member1.username = ?1
자바 코드여서 컴포지션이 되는 방법인 조립을 할수가 있다.
아래와 같이 allEq를 만들어서 where절에 넣어주도록 해보자.
// member 조회하고 usernameEq하니까 ageEq구나하고 생각하면 된다.
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(member)
.where(usernameEq(usernameCond), null)
// .where(allEq(usernameCond, ageCond))
.fetch();
}
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));
}
그리고 여러가지 장점이 있는데 순서대로 파악하면사 읽어보자.
2
/ member 조회하고 usernameEq하니까 ageEq구나하고 생각하면 된다.
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(member)
// .where(usernameEq(usernameCond), null)
.where(isServicable())
// .where(allEq(usernameCond, ageCond))
.fetch();
}
// 다른 쿼리에서도 재활용이 된다.
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(new QMemberDto(member.username, member.age ))
.from(member)
.where(isServicable())
.fetch();
}
3
// 다른 쿼리에서도 재활용이 된다.
private List<Member> searchMember2(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(new QMemberDto(member.username, member.age ))
.from(member)
.where(isServicable())
.fetch();
}
1
// 광고 상태 isValid, 날짜가 IN: isServicable 조건들이 여러개 나올 수가 있다.
// 이런식으로 작성하면 컴포지션이 된다.
// 아래와 같이 작성이 가능하다.
private BooleanExpression isServicable(String usernameCond, Integer ageCond) {
return isValid(usernameCond).and(DateBetweenIn(ageCond));
}
결론적으로
- `where`조건에 `null`값은 무시가 되고
- 메서드를 다른 쿼리에서도 재활용 할 수 있다.
- 쿼리 자체의 가독성이 높아진다. 그리고 조합이 가능하다.
- 편리하게 컴포지션 기능을 수행할 수 있다.
- `null` 체크는 주의해서 처리해야한다.
<출처 김영한: 실전! Querydsl >
https://www.inflearn.com/course/Querydsl-%EC%8B%A4%EC%A0%84/dashboard
실전! Querydsl - 인프런 | 강의
Querydsl의 기초부터 실무 활용까지, 한번에 해결해보세요!, - 강의 소개 | 인프런...
www.inflearn.com
'Spring > QueryDSL' 카테고리의 다른 글
SQL function 호출하기 (0) | 2022.04.21 |
---|---|
수정, 삭제 벌크 연산 - 배치 쿼리 (0) | 2022.04.21 |
동적 쿼리 - BooleanBuilder (0) | 2022.04.21 |
프로젝션과 결과 반환 - @QueryProjection (0) | 2022.04.21 |
프로젝션 결과 반환 - DTO 조회 (0) | 2022.04.21 |