querydsl 에서는 .groupBy() 를 통해 특정 컬럼에 대하여 집합으로 처리가 가능하다.
count, min, sum 과 같은 집합 함수도 사용할 수 있으며, 결과값은 querydsl에서 제공하는 Tuple 타입으로 반환한다.
예시)
@Test
public void aggregation() {
List<Tuple> resultList = queryFactory
.select(
member.count(),
member.age.sum(),
member.age.avg()
)
.from(member)
.fetch();
Tuple tuple = resultList.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);
}
예시2) - groupBy와 having
@Test
public void aggregation2() {
List<Tuple> resultList = queryFactory
.select(team.name, member.age.avg())
.from(member)
.join(member.team, team)
.groupBy(team.name)
.having(team.name.eq("A"))
.fetch();
assertThat(resultList.get(0).get(member.age.avg())).isEqualTo(15);
}
위에서도 잠깐 보았듯이 조인 역시 가능하다.
JPQL 문법처럼 조인대상을 연관관계가 드러나도록 명시해준다.
.join 은 기본적인 inner join 이며, leftJoin, rightJoin도 가능하다.
연관관계가 없는 두 테이블을 가져오고 싶은 경우(theta join) from 절에 두 테이블을 명시한다. (세타 조인과 외부 조인을 함께 사용하기 위해서는 밑에 설명할 on 절을 사용해야만 한다.)
예시)
@Test
public void join() throws Exception {
List<Member> result = queryFactory
.selectFrom(member)
.join(member.team, team)
.where(team.name.eq("A"))
.fetch();
assertThat(result)
.extracting("username")
.containsOnly("member1", "member2");
}
JPA 2.1 부터 지원하는 기능이다.
조인 대상 필터링, 연관관계 없는 엔티티 외부 조인이 가능하다.
조인 대상 필터링
내부 조인을 사용할 경우 on 절을 사용하나 where 절을 사용하나 동일한 기능으로 필터링을 할 수 있다.
외부 조인을 사용할 경우 on 절을 사용하여 데이터를 걸러 가져올 수 있다.
연관관계 없는 엔티티 외부 조인
세타 조인과 다르게 .leftJoin 을 사용한 뒤, 연관관계를 넣지 않고 테이블만을 넣어 조건없이 조인하고, on 절에 조인 조건을 정해준다.
페치 조인의 경우 조인 조건을 지정하고 그 뒤에 .fetchJoin() 을 명시해준다.
예시)
@PersistenceUnit
EntityManagerFactory emf;
@Test
public void fetchJoin() {
em.flush();
em.clear();
Member findMember = queryFactory
.selectFrom(member)
.join(member.team, team).fetchJoin()
.where(member.username.eq("member1"))
.fetchOne();
assertThat(emf.getPersistenceUnitUtil().isLoaded(findMember.getTeam()))
.isTrue();
}