개인적으로 오픈소스 프로젝트 중에 가장 좋아하시는 프로젝트

jpql을 자바 코드로 작성할 수 있도록 해준다. 기존에 criteria 라는 프로젝트가 있지만 사실상 매우 복잡하다. 실무에서 사용하기 힘들다.

JPA에서 잘 안 풀리는 문제가 동적 쿼리에 대한 문제가 있었다. (검색 조건)

Querydsl은 아예 다른 아이디어로 이 문제를 해결했다.

직접 한번 해보자. OrderSearch 쿼리를 해보자.

먼저 Q라는 파일을 생성해야 한다. 약간의 단점

buildscript {
    dependencies {
        classpath('gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:1.0.10')
    }
}

plugins {
    id 'org.springframework.boot' version '2.1.9.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
}

apply plugin: 'com.ewerk.gradle.plugins.querydsl'

group = 'jpabook'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-devtools'
    implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5'

    implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.7'

    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    implementation 'com.querydsl:querydsl-jpa'
    implementation 'com.querydsl:querydsl-apt'
}

def querydslDir = 'src/main/generated'

querydsl {
		library = 'com.querydsl:querydsl-apt'
		jpa = true
		querydslSourcesDir = querydslDir
}

sourceSets {
    main {
        java {
            srcDirs = ['src/main/java', querydslDir]
        }
    }
}

compileQuerydsl {
    options.annotationProcessorPath = configurations.querydsl
}

configurations {
    querydsl.extendsFrom compileClasspath
}

task → other → compileQuerydsl 실행

import static jpabook.jpashop.domain.QMember.*;
import static jpabook.jpashop.domain.QOrder.*;

@Repository
public class OrderRepository {

	private final EntityManager em;
	private final JPAQueryFactory query;

	public OrderRepository(EntityManager em) {
		this.em = em;
		this.query = new JPAQueryFactory(em);
	}

	public void save(Order order) {
		em.persist(order);
	}

	public Order findOne(Long id) {
		return em.find(Order.class, id);
	}

	public List<Order> findAll(OrderSearch orderSearch) {
		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 order.status.eq(statusCond);
	}

	private BooleanExpression nameLike(String nameCond) {
		if (!StringUtils.hasText(nameCond)) {
			return null;
		}
		return member.name.like(nameCond);
	}

	// ...