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 - ์ธํ๋ฐ (๊น์ํ)]