1. Querydsl이란?
Querydsl은 Java 애플리케이션에서 타입 안전한 쿼리를 작성할 수 있도록 도와주는 라이브러리로, 기본적으로 Q 클래스를 통해 엔티티 클래스의 속성에 접근하여 동적 쿼리를 생성한다. Q 클래스는 컴파일 타임에 타입 안전성을 제공하며, 이를 통해 쿼리 빌더(JPAQuery, SQLQuery 등)를 사용해 조건에 맞는 쿼리를 동적으로 구성할 수 있다. 쿼리 실행 시, 데이터베이스에 맞게 변환된 쿼리가 실행되며, 결과는 fetch(), fetchOne(), fetchCount() 등의 메서드를 통해 반환된다. 이 방식은 SQL 문자열을 직접 작성하는 대신 Java 코드로 쿼리를 작성함으로써 가독성을 높이고 오류를 줄이며, 동적 쿼리 생성을 통해 복잡한 조건을 효율적으로 처리할 수 있게 해준다.
그리고 Querydsl에서는 INSERT 쿼리를 직접 지원하지 않는다. Querydsl은 주로 SELECT 쿼리와 관련된 동적 쿼리 생성에 초점을 맞춘 라이브러리이기 때문에, 데이터베이스에 INSERT 작업을 수행하는 데는 다른 방법을 사용해야 한다.
Q 클래스가 뭔데?
Q 클래스는 Querydsl에서 타입 안전한 쿼리를 작성할 수 있도록 도와주는 특별한 클래스이다. 각 엔티티 클래스에 대해 자동으로 생성되는 이 클래스는 해당 엔티티의 필드를 정적 변수 로 선언하여, 쿼리에서 해당 필드를 참조할 수 있게 한다. 예를 들어, Member 라는 엔티티 클래스가 있으면 Querydsl은 QMember
라는 클래스를 자동으로 생성한다. 이 클래스는 Member 엔티티의 각 속성(필드)에 대해 타입-safe하게 접근할 수 있도록 도와주며, 이를 통해 쿼리 작성 시 컴파일 타임에 오류를 잡을 수 있게 한다. Q 클래스는 또한 JPAQuery, SQLQuery와 같은 쿼리 빌더와 함께 사용되어 동적이고 복잡한 쿼리를 작성하는 데 유용하게 활용된다.
2. Querydsl의 내부 동작
2.1. 쿼리 타입 생성
Querydsl은 엔티티 클래스나 다른 도메인 객체를 기반으로 Q 클래스를 생성한다. 이 Q 클래스는 엔티티의 필드를 정적 변수로 선언한 클래스로, 각 필드를 쿼리할 수 있도록 도와준다. 예를 들어, Member라는 엔티티가 있을 경우, Querydsl은 QMember라는 클래스를 자동으로 생성하여 해당 엔티티의 속성들에 접근할 수 있게 한다.
Member.java
@Entity
public class Member {
@Id
private Long id;
private String name;
private int age;
// getter, setter, etc.
}
QMember.java
public class QMember extends EntityPathBase<Member> {
public static final QMember member = new QMember("member");
public final NumberPath<Long> id = createNumber("id", Long.class);
public final StringPath name = createString("name");
public final NumberPath<Integer> age = createNumber("age", Integer.class);
public QMember(String variable) {
super(Member.class, forVariable(variable));
}
}
2.2. 쿼리 빌딩
Querydsl에서는 JPAQuery, SQLQuery, MongoQuery 등과 같은 쿼리 객체를 사용하여 동적 쿼리를 빌드한다. 이 쿼리 객체는 Q 클래스에 정의된 필드를 활용하여 쿼리의 조건을 동적으로 설정할 수 있게 해줍니다. 쿼리 객체는 메서드 체이닝 방식을 통해 쿼리를 구성할 수 있다.
QMember member = QMember.member;
JPAQuery<Member> query = new JPAQuery<>(entityManager);
List<Member> members = query.select(member)
.from(member)
.where(member.age.gt(30))
.fetch();
위의 예시에서는 member.age.gt(30)라는 조건을 통해 30세 이상인 회원들을 조회하는 쿼리를 동적으로 생성한다.
2.3.쿼리 실행 (Query Execution)
쿼리 빌딩이 완료되면, fetch(), fetchOne(), fetchCount() 등의 메서드를 호출하여 실제로 쿼리가 실행됩니다. 이 과정에서 JPA, SQL, MongoDB 등 사용된 데이터베이스에 맞는 쿼리가 생성되어 실행된다.
- fetch(): 결과를 리스트로 반환한다.
- fetchOne(): 단일 결과를 반환한다.
- fetchCount(): 결과의 개수를 반환한다.
쿼리 실행은 실제로 JPAQuery나 SQLQuery 객체에서 해당하는 데이터베이스 쿼리를 실행하게 됩니다. 이 때, 생성된 쿼리는 데이터베이스에 맞게 적절하게 변환되어 실행된다.
쿼리 메소드들은 아래 문서에서 찾아볼 수 있다.
http://querydsl.com/static/querydsl/latest/reference/html/
2.4. 컴파일 타임 타입 안전성
Querydsl의 중요한 특징 중 하나는 타입 안전성입니다. Q 클래스에서 제공하는 필드들은 모두 타입이 명확하게 정의되어 있기 때문에, 쿼리 작성 시 컴파일 타임에 오류를 체크할 수 있다. 예를 들어, member.age 필드에 잘못된 타입의 값을 넣으려 하면 컴파일 오류가 발생한다.
2.5. 동적 쿼리 지원
Querydsl은 조건에 따라 동적으로 쿼리를 수정할 수 있는 기능을 지원한다. 예를 들어, 사용자가 선택한 필터 조건에 따라 쿼리를 동적으로 구성할 수 있다.
BooleanBuilder builder = new BooleanBuilder();
if (name != null) {
builder.and(member.name.eq(name));
}
if (age != null) {
builder.and(member.age.gt(age));
}
List<Member> members = new JPAQuery<>(entityManager)
.select(member)
.from(member)
.where(builder)
.fetch();
2.6 결과 반환
쿼리 실행 후, fetch() 메서드를 사용하여 결과를 반환하면, Querydsl은 데이터베이스에서 반환된 레코드를 자바 객체로 매핑하여 반환 한다. 이 매핑 과정은 JPA의 EntityManager가 처리하게 되며, 결과는 List, Page, Optional 등의 형태로 반환될 수 있다.
'Spring' 카테고리의 다른 글
Spring Boot - ResponseEntity 클래스 (0) | 2025.01.11 |
---|---|
Spring Boot - Lombok (0) | 2024.04.03 |
Spirng Boot - REST API로 CRUD 만들기 (0) | 2024.04.03 |
Spring Security 살펴보기 (0) | 2024.02.22 |
스프링 핵심 원리 - 스프링 컨테이너 생성, 빈 조회 (0) | 2024.01.22 |