Bibi's DevLog ๐ค๐
[JPA] QueryDSL ์ฌ์ฉํ๊ธฐ ๋ณธ๋ฌธ
[210626]
[JPA] QueryDSL ์ฌ์ฉํ๊ธฐ
JPA ์ฌ์ฉ ์,
@Query
์ JPQL ๋์ ๋ฉ์๋๋ก SQL๋ฌธ์ ์ฒ๋ฆฌ ๊ฐ๋ฅ๋ฌธ๋ฒ ์ค๋ฅ๋ฅผ ์ปดํ์ผ ๋จ๊ณ์์ ํ์ธ ๊ฐ๋ฅ
build.gradle
์์กด์ฑ ์ถ๊ฐ
plugins {
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
}
...
dependencies {
implementation 'com.querydsl:querydsl-jpa'
implementation 'com.querydsl:querydsl-apt'
// ์๋๋ ์๋ค๋ฉด ์ถ๊ฐ (lombok์ ์ ํ)
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
..
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 ํ๋ก์ ํธ ์ ํ (Qํด๋์ค ์์ฑ)
https://jojoldu.tistory.com/372 <- ์ด ๋งํฌ์์ ์ด๊ธฐ ์ ํ ์ ๋ฐ๋ผํ๊ธฐ
Qํด๋์ค ์์ฑ ์ ๋ ๋ ...
-> ํน์ Project Structure - Project Settings - Modules ์์ Excluded Folders ์์ build๊ฐ ๋นจ๊ฐ์์ผ๋ก ์ค์ ๋์ด ์๋์ง ํ์ธํ๋ค.
์ฌ์ฉ ์ - IssueRepositorySupport
๊ธฐ์กด IssueRepository ์ธํฐํ์ด์ค ๋ฉ์๋์ @Query
์ปค์คํ
์ฟผ๋ฆฌ๋ก ๊ตฌํํ๋ ๋ถ๋ถ์ ๋ฉ์๋๋ก ๋์ฒดํ๋ ๋๋. ํธํ๋ค!
findByAssignee()
, findByCommentUserId()
: join๋ฌธ
QueryDSL Join๋ฌธ ์ฌ์ฉํ๊ธฐ ์ฐธ๊ณ ๋งํฌ..
Predicate : (๋ป : ์์ ๋ถ).
where()
๋ด์ ์กฐ๊ฑด ๋ค์ ๋ปํจ. predicate ์ฌ๋ฌ ๊ฐ๋ฅผ and๋ or๋ก ๋ฌถ์ ๊ฒ๋ predicate์. (boolean && boolean = boolean ์ธ ๊ฒ์ฒ๋ผ)
@Repository
public class IssueRepositorySupport extends QuerydslRepositorySupport {
private final JPAQueryFactory queryFactory;
public IssueRepositorySupport(JPAQueryFactory queryFactory) {
super(Issue.class);
this.queryFactory = queryFactory;
}
public List<Issue> findByTitle(String title) {
return queryFactory
.selectFrom(issue)
.where(issue.title.contains(title))
.fetch();
}
public List<Issue> findByStatusTrue() {
return queryFactory
.selectFrom(issue)
.where(issue.status.isTrue())
.fetch();
}
public List<Issue> findByStatusFalse() {
return queryFactory
.selectFrom(issue)
.where(issue.status.isFalse())
.fetch();
}
public List<Issue> findByAuthor(Long userId) {
return queryFactory
.selectFrom(issue)
.where(issue.user.id.eq(userId))
.fetch();
}
public List<Issue> findByAssignee(Long userId) {
return queryFactory
.selectFrom(issue)
.innerJoin(assignee)
.on(assignee.issueId.eq(issue.id))
.where(assignee.userId.eq(userId))
.fetch();
}
public List<Issue> findByCommentUserId(Long userId) {
return queryFactory
.selectFrom(issue)
.innerJoin(comment)
.on(comment.issueId.eq(issue.id))
.where(comment.user.id.eq(userId))
.fetch();
}
public List<Issue> getFilteredIssues(IssueFilter issueFilter) {
JPAQuery query = queryFactory
.selectFrom(issue)
.where(getPredicate(issueFilter));
Long userId = issueFilter.getAssignee();
if (userId != null) {
query.innerJoin(assignee)
.on(assignee.issueId.eq(issue.id))
.where(assignee.userId.eq(userId));
}
userId = issueFilter.getCommenter();
if (userId != null) {
query.innerJoin(comment)
.on(comment.issueId.eq(issue.id))
.where(comment.user.id.eq(userId));
}
return query.fetch();
}
public Predicate getPredicate(IssueFilter filter) {
return new PredicateBuilder(issue.isNotNull())
.containsAnd(issue.title, filter.getTitle())
.isBooleanAnd(issue.status, filter.getStatus())
.isLongEqualAnd(issue.user.id, filter.getAuthor())
.build();
}
}
์์ getPredicate()
์ ํ์ํ ํด๋์ค์ธ PredicateBuilder
package com.codesquad.issuetracker.domain.issue;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.BooleanPath;
import com.querydsl.core.types.dsl.NumberPath;
import com.querydsl.core.types.dsl.StringPath;
public class PredicateBuilder {
private final BooleanExpression predicate;
public PredicateBuilder(BooleanExpression predicate) {
this.predicate = predicate;
}
public PredicateBuilder containsAnd(StringPath qValue, String rValue) {
if (rValue != null) {
return new PredicateBuilder(predicate.and(qValue.containsIgnoreCase(rValue)));
}
return this;
}
public PredicateBuilder isBooleanAnd(BooleanPath qValue, Boolean rValue) {
if (rValue != null) {
return (rValue) ? new PredicateBuilder(predicate.and(qValue.isTrue()))
: new PredicateBuilder(predicate.and(qValue.isFalse()));
}
return this;
}
public PredicateBuilder isLongEqualAnd(NumberPath qValue, Long rValue) {
if (rValue != null) {
return new PredicateBuilder(predicate.and(qValue.eq(rValue)));
}
return this;
}
public BooleanExpression build() {
return predicate;
}
}