@BeforeEach
void setUp() {
queryFactory = new JPAQueryFactory(em);
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
em.persist(teamA);
em.persist(teamB);
Member member1 = new Member("member1", 10, teamA);
Member member2 = new Member("member2", 20, teamA);
Member member3 = new Member("member3", 30, teamB);
Member member4 = new Member("member4", 40, teamB);
em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
}
@Test
public void aggregation() throws Exception {
List<Tuple> result = queryFactory
//...2
.select(member.count(), //회원수
member.age.sum(), //나이 합
member.age.avg(), //평균 나이
member.age.max(), //최대 나이
member.age.min()) //최소 나이
.from(member)
.fetch();
Tuple tuple = result.get(0);
assertThat(tuple.get(member.count())).isEqualTo(4);
assertThat(tuple.get(member.age.sum())).isEqualTo(100);
assertThat(tuple.get(member.age.avg())).isEqualTo(25);
assertThat(tuple.get(member.age.max())).isEqualTo(40);
assertThat(tuple.get(member.age.min())).isEqualTo(10);
}
Tuple
→ 자세히
QueryDsl 이 제공하는 Tuple 입니다.
import com.querydsl.core.Tuple;
select 절의 데이터 타입이 Member 같은 단일 타입이 아니라 여러개가 들어오는 경우에 Tuple 을 사용하면 됩니다.
하지만 실무에서 Tuple 을 많이 사용하지는 않고 DTO 로 직접 뽑아오는 방법을 많이 사용합니다.
get() 로 Tuple 에 있는 값을 꺼내올 수 있습니다.
JPQL이 제공하는 모든 집합 함수를 제공합니다.
팀의 이름과 각 팀의 평균 연령을 구하는 GroupBy 테스트 코드를 작성해봅시다.
import static study.querydsl.entity.QTeam.team;
@BeforeEach
void setUp() {
queryFactory = new JPAQueryFactory(em);
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");
em.persist(teamA);
em.persist(teamB);
Member member1 = new Member("member1", 10, teamA);
Member member2 = new Member("member2", 20, teamA);
Member member3 = new Member("member3", 30, teamB);
Member member4 = new Member("member4", 40, teamB);
em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);
}
@Test
public void group() {
List<Tuple> result = queryFactory
.select(team.name, member.age.avg())
.from(member)
.join(member.team, team)
.groupBy(team.name)
.fetch();
Tuple teamA = result.get(0);
Tuple teamB = result.get(1);
assertThat(teamA.get(team.name)).isEqualTo("teamA");
assertThat(teamA.get(member.age.avg())).isEqualTo(15);
assertThat(teamB.get(team.name)).isEqualTo("teamB");
assertThat(teamB.get(member.age.avg())).isEqualTo(35);
}
테스트 코드를 실행해서 쿼리를 봅시다.
JPQL 을 보면 member와 team 을 내부조인하고 team.name 으로 group by 를 했습니다.
SQL 도 동일하죠.
마찬가지로 having 조건도 넣을 수 있습니다.
예를 들어, item 엔티티가 있고 가격에 대한 데이터를 가지고 있을 때 1000원이 넘는 item 만 뽑고 싶다면 아래처럼 코드를 작성할 수 있겠죠.