반응형
QueryDSL
실무에서는 조건에 따라서 실행되는 쿼리가 달라지는 동적 쿼리를 많이 사용한다.
이전 방법
public List<Order> findAllByString(OrderSearch orderSearch) {
//language=JPAQL
String jpql = "select o From Order o join o.member m";
boolean isFirstCondition = true;
//주문 상태 검색
if (orderSearch.getOrderStatus() != null) {
if (isFirstCondition) {
jpql += " where";
isFirstCondition = false;
} else {
jpql += " and";
}
jpql += " o.status = :status";
}
//회원 이름 검색
if (StringUtils.hasText(orderSearch.getMemberName())) {
if (isFirstCondition) {
jpql += " where";
isFirstCondition = false;
} else {
jpql += " and";
}
jpql += " m.name like :name";
}
TypedQuery<Order> query = em.createQuery(jpql, Order.class) .setMaxResults(1000); //최대 1000건
if (orderSearch.getOrderStatus() != null) {
query = query.setParameter("status", orderSearch.getOrderStatus());
}
if (StringUtils.hasText(orderSearch.getMemberName())) {
query = query.setParameter("name", orderSearch.getMemberName());
}
return query.getResultList();
}
- 동적 쿼리를 위한 JPQL 사용 방식
public List<Order> findALlByCriteria(OrderSearch orderSearch) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
Root<Order> o = cq.from(Order.class);
Join<Order, Member> m = o.join("member", JoinType.INNER);
List<Predicate> criteria = new ArrayList<>();
//주문 상태 검색
if (orderSearch.getOrderStatus() != null) {
Predicate status = cb.equal(o.get("status"),
orderSearch.getOrderStatus());
criteria.add(status);
}
//회원 이름 검색
if (StringUtils.hasText(orderSearch.getMemberName())) {
Predicate name =
cb.like(m.<String>get("name"), "%" +
orderSearch.getMemberName() + "%");
criteria.add(name);
}
cq.where(cb.and(criteria.toArray(new Predicate[criteria.size()])));
TypedQuery<Order> query = em.createQuery(cq).setMaxResults(1000); //최대 1000건
return query.getResultList();
}
- 동적 쿼리를 위한 Criteria 사용 방식
QueryDSL
//querydsl 추가
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}
plugins {
id 'org.springframework.boot' version '2.6.6'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
// querydsl 추가
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
}
group = 'jpabook'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5'
implementation 'org.springframework.boot:spring-boot-devtools'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.8.0'
implementation 'org.springframework.boot:spring-boot-starter-web'
//querydsl 추가
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
implementation "com.querydsl:querydsl-apt:${queryDslVersion}"
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
//querydsl 추가 시작
def querydslDir = "$buildDir/generated/querydsl"
querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main.java.srcDir querydslDir
}
configurations {
querydsl.extendsFrom compileClasspath
}
compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}
//querydsl 추가 끝
- 스프링부트 2.6 부터는 querydsl 5.0.0 버전을 사용해야한다. (작성 후 Gradle - other - compileQuerydsl 더블클릭)
- 다음과 같이 Q클래스들이 생성된 것을 볼 수 있다.
public List<Order> findAll(OrderSearch orderSearch) {
QOrder order = QOrder.order;
QMember member = QMember.member;
JPAQueryFactory query = new JPAQueryFactory(em);
return query.select(order)
.from(order)
.join(order.member, member)
.where(statusEq(orderSearch.getOrderStatus()), nameLike(orderSearch.getMemberName()))
.limit(1000)
.fetch();
}
private BooleanExpression statusEq(OrderStatus statusCond) {
if (statusCond == null) {
return null;
}
return QOrder.order.status.eq(statusCond);
}
private BooleanExpression nameLike(String nameCond) {
if (!StringUtils.hasText(nameCond)) {
return null;
}
return QMember.member.name.like(nameCond);
}
- 다음과 같이 SQL과 모양이 유사하면서 자바 코드로 동적 쿼리를 편리하게 작성할 수 있다.
Querydsl은 JPQL 코드를 만드는 빌더 역할 뿐이다. JPQL을 잘 이해하면 금방 익힐 수 있다.
본 포스팅은 인프런 김영한님 강의(실전! 스프링 부트와 JPA 활용2)를 토대로 정리한 내용입니다.
반응형