*개요
Spring Data Jpa를 사용하면서, 동적 쿼리를 사용하고 또 컴파일 시점에 오류를 잡아주는 QueryDSL을 사용하기 위해 셋팅을 먼저 합니다.
spring boot프로젝트에서 빌드 도구는 gradle을 사용했습니다. build.gradle에서 라이브러리를 추가합니다
1. plugins에 다음을 추가합니다
//Querydsl
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'
2. dependencies에 다음을 추가합니다
//Querydsl
implementation 'com.querydsl:querydsl-jpa'
3. 파일 맨 아래에 독립적으로 다음을 추가합니다
def querydslDir = "$buildDir/generated/querydsl"
querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main.java.srcDir querydslDir
}
configurations {
querydsl.extendsFrom compileClasspath
}
compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}
3개를 추가했다면, Reload All Gradle Projects로 의존성을 적용시킵니다.
이후 오른쪽에 있는 Gradle을 클릭해 [Tasks] - [other] - [compileJava]를 클릭해서 컴파일을 합니다.
저는 아래와 같은 에러가 발생했는데, 각 엔티티에서 @Build.Default로 List를 초기화하거나, final을 사용하라고 합니다. @Builder가 초기화할 때 제대로 설정을 하지 못하는 것 같습니다.
따라서 변수 위에 @Builder.Default를 추가하여 다시 compile하니 성공했습니다.
build.gradle에 아래와 같이 파일 경로 설정을 했으므로 해당 위치에 가서 확인합니다.
아래와 같이 build 폴더의 generated에 도메인 이름 앞에 Q가 접두사로 붙어서 생성됩니다.
참고로 빌드도구가 gradle이기 때문에 아래 명령어로 build파일을 전부 삭제할 수 있습니다.
./gradlew clean
querydsl 파일들을 다시 생성시키고 싶으면 compile하면 됩니다.
./gradlew compileQuerydsl
이렇게 생성된 Q관련 파일들은 git에 push하면 안됩니다. 내부 설정파일들이기 때문입니다. 현재는 다행히 build 폴더 안에 있기 때문에 어차피 .gitignore에서는 build폴더가 추가되어 있어서 추가 설정이 필요하지 않습니다.
Querydsl 실습을 짧게 해봅니다. Hello 도메인을 만듭니다.
@Entity
@Getter
@Setter
public class Hello {
@Id
@GeneratedValue
private Long id;
}
Querydsl로 생성된 QHello는 아래와 같습니다.
/**
* QHello is a Querydsl query type for Hello
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QHello extends EntityPathBase<Hello> {
private static final long serialVersionUID = 1223442224L;
public static final QHello hello = new QHello("hello");
public final NumberPath<Long> id = createNumber("id", Long.class);
public QHello(String variable) {
super(Hello.class, forVariable(variable));
}
public QHello(Path<? extends Hello> path) {
super(path.getType(), path.getMetadata());
}
public QHello(PathMetadata metadata) {
super(Hello.class, metadata);
}
}
간단히 Querydsl 문법으로 조회하는 테스트를 합니다.
@SpringBootTest
@Transactional
class QueryDslApplicationTests {
//@PersistenceContext
@Autowired
EntityManager em;
@Test
void contextLoads() {
Hello hello = new Hello();
em.persist(hello);
JPAQueryFactory query = new JPAQueryFactory(em);
//QHello qHello = new QHello("h");
QHello qHello = QHello.hello;
Hello result = query
.selectFrom(qHello)
.fetchOne();
Assertions.assertThat(result).isEqualTo(hello);
Assertions.assertThat(result.getId()).isEqualTo(hello.getId());
}
}
query 조회문에서 보다시피, selectFrom에는 qHello가 들어갑니다. QHello가 왜 필요한지 알 수 있습니다.
또한 new QHello("h");로 객체를 생성할수도 있지만, QHello에 이미 내부에 정의된 내용에 따라 QHello.hello로 생성가능합니다
마지막으로 application.yml을 다음과 같이 설정합니다. 특히 최초 1번은 url을 jdbc:h2:~/querydsl로 설정하고 실행시킨 후, ~/querydsl.mv.db가 생성된 것을 확인한 후에 jdbc:h2:tcp://localhost/~/querydsl로 교체합니다.
spring:
datasource:
#url: jdbc:h2:~/querydsl
url: jdbc:h2:tcp://localhost/~/querydsl
username: sa
password:
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto: create
properties:
hibernate:
# show_sql: true
format_sql: true
logging.level:
org.hibernate.SQL: debug
# org.hibernate.type: trace