JPA๋ฅผ ์ฌ์ฉํ๋ฉด์ ๊ตฌํํ ์ ์๋ ๋ณต์กํ ์ฟผ๋ฆฌ๋ฅผ ๊ทน๋ณตํ ์ ์๋ QueryDSL์ ๋ํด์ ์์๋ณด์.
๋จผ์ ๊ฐ๋จํ๊ฒ ์ค๋ช ํ์๋ฉด QueryDSL์ ์ฟผ๋ฆฌ๋ฅผ ์๋ฐ์ฝ๋๋ก ์์ฑํ์ฌ ์ฅ์ ์ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ์ด๋ค.
๋ ์์ธํ๊ฒ ์์๋ณด์.

์ 3๊ฐ์ง ์ฅ์ ์ด ๊ฐ๋ ฅํ์ฌ QueryDSL์ ์ฌ์ฉํ๋๋ฐ ์ถฉ๋ถํ ์ด์ ๊ฐ ๋๋ค๊ณ ์๊ฐํ๋ค.
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'study'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//test ๋กฌ๋ณต ์ฌ์ฉ
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
//Querydsl ์ถ๊ฐ
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}
tasks.named('test') {
useJUnitPlatform()
}
clean {
delete file('src/main/generated')
}
plugins {
id 'org.springframework.boot' version '2.6.5'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
ext["hibernate.version"] = "5.6.5.Final"
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
//JdbcTemplate ์ถ๊ฐ
//implementation 'org.springframework.boot:spring-boot-starter-jdbc'
//MyBatis ์ถ๊ฐ
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
//JPA, ์คํ๋ง ๋ฐ์ดํฐ JPA ์ถ๊ฐ
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
//Querydsl ์ถ๊ฐ
implementation 'com.querydsl:querydsl-jpa'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
//H2 ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ถ๊ฐ
runtimeOnly 'com.h2database:h2'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//ํ
์คํธ์์ lombok ์ฌ์ฉ
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
}
tasks.named('test') {
useJUnitPlatform()
}
//Querydsl ์ถ๊ฐ, ์๋ ์์ฑ๋ Qํด๋์ค gradle clean์ผ๋ก ์ ๊ฑฐ
clean {
delete file('src/main/generated')
}
private final JPAQueryFactory queryFactory;
public MemberRepositoryImpl(EntityManager em) {
this.queryFactory = new JPAQueryFactory(em);
}
Member findMember = queryFactory
.select(member)
.from(member)
.where(member.username.eq("member1"))
.fetchOne();
QueryDSL์ ์ด์ฉํ ๊ธฐ๋ณธ์ ์ธ where์ ์ ์ด์ฉํ ์กฐํ์ด๋ค.Member findMember = queryFactory
.selectFrom(member)
.where(member.username.eq("member1").and(member.age.between(10, 30)))
.fetchOne();
.where(member.username.eq("member1"), member.age.between(10, 30))์ ๊ฐ์ดย ,๋ฅผ ์ด์ฉํด ๊ฐ๋จํ๊ฒ ์ฌ์ฉํ ์๋ ์๋ค.null์ผ ๊ฒฝ์ฐ ๋ฌด์ํ๋ค. ๋ฐ๋ผ์ ๋์ ์ฟผ๋ฆฌ๋ฅผ ๊น๋ํ๊ฒ ๊ตฌ์ฑํ ์ ์๋ค.eq(): A = ?ne(): A != ?eq().not(): A != ?isNotNull(): A is not nullin(): A in (?)notIn(): A not in (?)between(): A between ?, ?goe(): A >= ?gt(): A > ?loe(): A <= ?lt(): A < ?like(): A like ?contains(): A like "%?%"startWith(): A like "?%?fetch(): ๋ฆฌ์คํธ๋ฅผ ์กฐํํ๋ค, ๊ฐ์ด ์์ ๋์๋ ๋น ๋ฆฌ์คํธ๊ฐ ๋ฐํ๋๋ค.fetchOne(): ๋จ ๊ฑด ์กฐํnull์ ๋ฆฌํดํ๋ค.NonUniqueResultException์ด ๋ฐ์ํ๋ค.fetchFirst():ย limit(1).fetchOne()๊ณผ ๋์ผํ๋ค.fetchResults(): ํ์ด์ง ์ ๋ณด๋ฅผ ํฌํจํ์ฌ total count์ฟผ๋ฆฌ๋ฅผ ์ถ๊ฐ๋ก ์คํ์ํจ๋ค.getTotal()๊ณผย getResult()๋ฉ์๋๋ก ์ ๋ณด๋ฅผ ์กฐํํ ์ ์๋ค.fetchCount(): count์ฟผ๋ฆฌ๋ก ๋ณํํด count์๋ฅผ ์กฐํํ๋ค.QueryResults<Member> queryResults = queryFactory
.selectFrom(member)
.orderBy(member.username.desc())
.offset(1)
.limit(2)
.fetchResults();
offset(): ์์์ ์ ์ค์ ํ๋ค.limit(): ์ต๋ ์กฐํ ์๋ฅผ ์ค์ ํ๋ค.listResults():ย QueryResultsํ์
์ผ๋ก ๋ฆฌํด๋ฐ๋๋ค.QueryResults.getTotal(): ์ ์ฒด ์ ์กฐํQueryResults.getLimit(): limit ์กฐํQueryResults.getOffset(): offset ์กฐํQueryResults.getResults(): ๊ฒฐ๊ณผ๊ฐ ์กฐํorderBy๋ฅผ ์ฌ์ฉํ๋ค.asc(): ์ค๋ฆ์ฐจ์ ์ ๋ ฌdesc(): ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌnullsLast(),ย nullsFirst: null๊ฐ์ ์์น๋ฅผ ์ค์ ํ๋ค.asc().nullsLast()์ ๊ฐ์ ํํ๋ก ์ฌ์ฉํ๋ค.List<Tuple> result = queryFactory
.select(team.name, member.age.avg())
.from(member)
.join(member.team, team)
.groupBy(team.name)
.fetch();
COUNT(): ๊ฐ์SUM(): ํฉAVG(): ํ๊ท MAX(): ์ต๋MIN(): ์ต์groupBy(): ํ๋๋ช
์ ์ด์ฉํด ๊ทธ๋ฃนํํ๋ค.having(): having์ ์ฌ์ฉList<Member> result = queryFactory
.selectFrom(member)
.join(member.team, team)
.where(team.name.eq("teamA"))
.fetch();
.join(์กฐ์ธ๋์, ๋ณ์นญ์ฟผ๋ฆฌํ์
)์ ํํ๋ก ์ฌ์ฉํ๋ค.innerJoin(): sql์ innerJoinleftJoin(): sql์ leftJoinrightJoin(): sql์ rightJoinfullJoin(): sql์ fullJoinon(): join์ on์ ์ ์ฌ์ฉํ๋ค.innerJoin์ฌ์ฉ์ย where์ ๋ก ํํฐ๋งํ๋ ๊ฒ๊ณผ ๋์ผํ๋ค.fetch(): join์ ํ์น์กฐ์ธ์ ์ ์ฉํ๋ค.innerJoin(~~).fetch()์ ํํ๋ก ์ฌ์ฉํ๋ค.QMember memberSub = new QMember("memberSub");
List<Member> result = queryFactory
.selectFrom(member)
.where(member.age.eq(
JPAExpressions
.select(memberSub.age.max())
.from(memberSub)
))
.fetch();
JPAExpressions๋ฅผ ์ด์ฉํ๋ค.QType์ ์ ์ํ์ฌ ์ฌ์ฉํ๋ค.FROM์ ์ ์๋ธ์ฟผ๋ฆฌList<String> result = queryFactory
.select(member.age
.when(10).then("์ด์ด")
.when(20).then("์ค๋ฌด์ด")
.otherwise("๊ธฐํ")
)
.from(member)
.fetch();
when(): sql์ whenthen(): when์ ํด๋นํ ๋otherwise(): ๋๋จธ์ง ์ํฉNumberExpression<Integer> rankPath = new CaseBuilder()
.when(member.age.between(0, 20)).then(2)
.when(member.age.between(21, 30)).then(1)
.otherwise(3);
List<Tuple> result = queryFactory
.select(member.username, Expressions.constant("A"))
.from(member)
.fetch();
List<Tuple> result = queryFactory
.select(member.username.concat("_").concat(member.age.stringValue()), member.age)
.from(member)
.where(member.username.eq("member1"))
.fetch();
Expressions.constant(): ์์๋ฅผ ๋ํ ๋ ์ฌ์ฉํ๋ค.concat(): ๋ฌธ์๋ฅผ ๋ํ ๋ ์ฌ์ฉํ๋ค.์ถ์ฒ: https://well-made-codestory.tistory.com/59?category=1098576 [SJ BackEnd Log:ํฐ์คํ ๋ฆฌ]
์ถ์ฒ: https://well-made-codestory.tistory.com/59?category=1098576 [SJ BackEnd Log:ํฐ์คํ ๋ฆฌ]
์ถ์ฒ: https://www.inflearn.com/course/Querydsl-%EC%8B%A4%EC%A0%84/dashboard [์ค์ ! Querydsl - ์ธํ๋ฐ (๊น์ํ)]