Querydsl 조회 결과 Map<K, V> 타입으로 매핑하기
Aggregate Results as Map with Querydsl
Querydsl을 활용하여 데이터베이스에서 데이터셋을 가져올 때 Map<K, V>
타입으로 결과를 가공하는 방법에 대해 살펴봅니다.
Working with ResultTransformer
Querydsl에서 제공하는 ResultTransformer
인터페이스를 활용하면 조회 결과를 Map<K, V>
으로 전환할 수 있습니다.
MemberRepositoryImpl.java
@Override
public Map<String, List<Member>> fetch() {
return queryFactory
.from(member)
.innerJoin(member.team, team).fetchJoin()
.transform(groupBy(team.name).as(list(member)));
}
transform(groupBy())
: 쿼리 조회 결과에서team.name
값을 Key로, 그리고 해당team
에 소속된member
리스트를 Value로 전환합니다.
참고로, 현재 Spring Boot 3.x 버전에서 transform()
을 사용하면 NoSuchMethodError
예외가 발생합니다.
Caused by: java.lang.NoSuchMethodError: 'java.lang.Object org.hibernate.ScrollableResults.get(int)'
EntityManager
를 기반으로 JPQLTemplates
이 자동으로 설정돼야 하는데 이 과정에서 문제가 발생한 것입니다. 최신 Hibernate 버전과의 호환성 문제로 짐작되며 해당 이슈는 Querydsl GitHub Issues에 Open된 상태입니다.
현재 제시된 해결 방법은 JPAQueryFactory
인스턴스의 JPQLTemplates
을 DEFAULT
로 직접 지정하는 것입니다.
QuerydslConfig.java
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(JPQLTemplates.DEFAULT, entityManager);
}
Querydsl의 tranform()
도 결국엔 메모리 위에서 동작하는 것이기 때문에, 상황에 따라 Querydsl을 통한 데이터 조회는 List<T>
타입으로 가져온 다음 Java Stream API를 통해 Map<K, V>
으로 분류하는 것이 제어 및 역할 분리에 용이할 수도 있습니다.
- Spring
- JPA
- Querydsl