Q클래스는 QueryDSL 사용하시 자동 생성되는 엔티티 기반 클래스이다. JPA 엔티티를 기반으로 동적으로 쿼리를 작성할 수 있도록 지원한다. JPAQueryFactory와 함께 사용하면 가독성이 좋고 직관적인 쿼리 작성이 가능하다.
gradle의 경우 Q클래스의 자동 생성 위치는 build/generated/sources/annotationProcessor/java/main/패키지 경로~ 이다.

Q클래스 내부에서 엔티티의 필드들을 표현하는 경로 객체이다.
즉, Q클래스는 엔티티 전체를 대표하는 클래스라면, Path 클래스는 그 안의 필드들을 타입에 맞게 다루는 객체이다.
-> Q클래스 내부에 Path 클래스가 포함되어 있다.
| QueryDSL 타입 | 설명 | 사용 예시 |
|---|---|---|
StringPath | 문자열 필드 | QUser.user.name.eq("John") |
NumberPath<T> | 숫자 필드 (Integer, Long, Double, etc.) | QUser.user.age.gt(18) |
BooleanPath | Boolean 타입 필드 | QUser.user.active.isTrue() |
DatePath<T> | java.sql.Date 타입 날짜 필드 | QOrder.order.date.eq(LocalDate.of(2024, 2, 13)) |
DateTimePath<T> | java.time.LocalDateTime 등의 필드 | QOrder.order.createdAt.before(LocalDateTime.now()) |
TimePath<T> | java.sql.Time 타입 필드 | QEvent.event.startTime.after(LocalTime.of(14, 0)) |
SimplePath<T> | 임의의 객체 타입 필드 | QUser.user.customField.eq(customObject) |
EnumPath<T> | Enum 타입 필드 | QUser.user.role.eq(Role.ADMIN) |
ComparablePath<T> | Comparable<T> 인터페이스를 구현한 객체 | QUser.user.someComparableField.between(a, b) |
BeanPath<T> | Java Bean 객체 타입 | QUser.user.address.city.eq("Seoul") |
ArrayPath<T, A> | 배열 필드 (T[] 타입) | QUser.user.tags.contains("Spring") |
CollectionPath<E, Q> | Collection<E> 타입 필드 | QUser.user.roles.contains(Role.ADMIN) |
SetPath<E, Q> | Set<E> 타입 필드 | QUser.user.permissions.contains(Permission.READ) |
ListPath<E, Q> | List<E> 타입 필드 | QUser.user.friends.contains(QUser.user) |
MapPath<K, V, Q> | Map<K, V> 타입 필드 | QUser.user.attributes.get("nickname").eq("Johnny") |
✔ 1️⃣ 기본 필드 메서드
QUser user = QUser.user;
user.id // NumberPath<Long> -> 숫자 필드
user.username // StringPath -> 문자열 필드
user.age // NumberPath<Integer> -> 숫자 필드
user.isDelete // BooleanPath -> 불린 필드
✔ 2️⃣ 조건 메서드
user.username.eq("John") // username = 'John'
user.age.goe(20) // age >= 20
user.age.loe(30) // age <= 30
user.username.contains("oh") // username LIKE '%oh%'
user.isDelete.isFalse() // isDelete = false
user.id.in(1L, 2L, 3L) // id IN (1,2,3)
✔ 3️⃣ BooleanExpression 활용
-> 파라미터가 null이면 조건을 제외할 수 있다 (JPQL에서는 불가능)
public BooleanExpression usernameEq(String username) {
return username != null ? QUser.user.username.eq(username) : null;
}
public BooleanExpression ageGoe(Integer age) {
return age != null ? QUser.user.age.goe(age) : null;
}
public List<User> findUsers(String username, Integer age) {
return queryFactory
.selectFrom(QUser.user)
.where(usernameEq(username), ageGoe(age)) // null이면 무시됨
.fetch();
}
QueryDSL에서 JPA 기반 쿼리를 쉽게 생성할 수 있도록 도와주는 객체이다. JPQL이나 Criteria API보다 가독성이 좋고 타입 안정성이 보장된다.
EntityManager 기반으로 동작하며, (Q클래스 기반의) 타입 안정성을 보장, 동적 쿼리 작성 가능(BooleanExpression 활용), 다양한 메서드를 지원한다.
@Autowired
private JPAQueryFactory queryFactory;
public User findByUsername(String username) {
return queryFactory
.selectFrom(QUser.user)
.where(QUser.user.username.eq(username))
.fetchOne();
}
public List<User> findUsers(String username, Integer minAge) {
return queryFactory
.selectFrom(QUser.user)
.where(
QUser.user.username.like("%" + username + "%"),
QUser.user.age.goe(minAge) // age >= minAge
)
.fetch();
}
public List<User> findUsersWithPagination(int page, int size) {
return queryFactory
.selectFrom(QUser.user)
.orderBy(QUser.user.age.desc())
.offset((page - 1) * size)
.limit(size)
.fetch();
}
| 메서드 | 설명 |
|---|---|
fetchOne() | 단일 결과 조회 (여러 개면 예외) |
fetchFirst() | 첫 번째 결과만 조회 |
fetch() | 리스트 조회 (비어 있으면 빈 리스트) |
fetchResults() | 페이징용 (fetchCount() + fetch()) (⚠️ Hibernate 6부터 지원 중단) |
fetchCount() | 개수 조회 (⚠️ Hibernate 6부터 지원 중단) |
count(), sum(), avg(), max(), min() | 집계 함수 |
groupBy(), having() | 그룹화 및 조건 |
orderBy() | 정렬 |
limit(), offset() | 페이징 |