Querydsl을 사용하게 되면 상황에 따라 다르게 적용을 할 수 있는 동적쿼리를 손쉽게 짤 수 있습니다.
동적쿼리를 짜는 방식은 대표적으로 두 가지가 있습니다. 지금부터 알아보도록 하겠습니다.
BooleanBuilder 사용 방식
BooleanBuilder란 아래와 같이 BooleanBuilder 생성자를 생성 후,
아래와 같이 if문을 통해서 각 데이터의 조건에 맞게 코드를 작성하는 것입니다.
아래 코드와 같이 데이터가 많지 않아 작성해야 할 if문이 많지 않다면 쿼리문이 깔끔하게 보이겠지만,
데이터가 많아진다면 추가해야 할 조건문이 많아져 쿼리문을 추적하기 어려울 것입니다.
public List<MemberTeamDto> searchByBuilder(MemberSearchCondition condition) {
BooleanBuilder builder = new BooleanBuilder();
if (hasText(
condition.getUserName())) { // hasText = 값이 있을 경우 True, 공백 또는 ""일 경우 False 리턴
builder.and(member.username.eq(condition.getUserName()));
}
if (hasText(condition.getTeamName())) {
builder.and(team.name.eq(condition.getTeamName()));
}
if (condition.getAgeGoe() != null) {
builder.and(member.age.goe(condition.getAgeGoe()));
}
if (condition.getAgeLoe() != null) {
builder.and(member.age.loe(condition.getAgeLoe()));
}
return queryFactory
.select(new QMemberTeamDto(
member.id.as("memberId"),
member.username,
member.age,
team.id.as("teamId"),
team.name.as("teamName")))
.from(member)
.leftJoin(member.team, team)
.where(builder) //생성한 builder 객체를 where절에 작성해줌
.fetch();
}
BooleanExpression 사용 방식
BooleanExpression은 BooleanBuilder의 단점을 개선할 수 있는 방식인데요,
보시다시피 BooleanBuilder와 쿼리를 짠 방식이 비슷하면서 조금은 다릅니다.
아래 코드는 위 코드와 같은 데이터를 통해 쿼리문을 짠 코드인데요,
BooleanBuilder는 생성한 객체를 where절에 넘겼다면,
BooleanExpression은 where절에 다중 파라미터를 사용하는 방식입니다.
참고로 여기서 where절에 null 값은 무시가 됩니다.
public List<MemberTeamDto> search(MemberSearchCondition condition) {
return queryFactory
.select(new QMemberTeamDto(
member.id.as("memberId"),
member.username,
member.age,
team.id.as("teamId"),
team.name.as("teamName")))
.from(member)
.leftJoin(member.team, team)
.where(
userNameEq(condition.getUserName()),
teamNameEq(condition.getTeamName()),
ageGoe(condition.getAgeGoe()),
ageLoe(condition.getAgeLoe())
)
.fetch();
}
private BooleanExpression userNameEq(
String userName) { //BooleanExpression을 사용해야 메서드끼리 조합이 가능해짐, 재사용도 가능
return hasText(userName) ? member.username.eq(userName) : null;
}
private BooleanExpression teamNameEq(String teamName) {
return hasText(teamName) ? team.name.eq(teamName) : null;
}
private BooleanExpression ageGoe(Integer ageGoe) {
return ageGoe != null ? member.age.goe(ageGoe) : null; //goe = 크거나 같다
}
private BooleanExpression ageLoe(Integer ageLoe) {
return ageLoe != null ? member.age.loe(ageLoe) : null; //loe = 작거나 같다
}
BooleanExpression을 사용하면 생성해야 할 메서드가 많아지겠지만,
where절 내에서 메서드명을 보고 손쉽게 쿼리를 파악할 수 있어 가독성이 높아진다는 장점이 있습니다.
또한 아래와 같이 메서드를 조합하여 사용할 수 있어 재사용성이 증가한다는 장점이 있습니다.
private BooleanExpression ageBetween(int ageLoe, int ageGoe) { //메서드 조립
return ageLoe(ageLoe).and(ageGoe(ageGoe));
}
필요에 따라 다르게 사용할 수 있지만,
가독성과 재사용성이 높다는 장점을 고려하면 BooleanExpression을 활용하여 쿼리를 짜는 것을 권장합니다.
Reference
- 인프런 김영한 - 실전! Querydsl
'Spring' 카테고리의 다른 글
[Spring Boot] Querydsl 초기 세팅 (Gradle, Querydsl 5.0.0) (6) | 2023.07.31 |
---|---|
[Spring Boot] Spring Data JPA에서 BaseEntity 사용하기 (10) | 2023.07.26 |
Junit5에서 assertThat()과 equalTo()가 선언이 안되는 경우 (0) | 2023.05.08 |
@RequestParam과 @Pathvariable의 차이점 (0) | 2023.05.08 |
[IntelliJ] 테스트 코드 단축키 설정 (0) | 2023.05.08 |