ํ๋ก์ ์
ํ๋ก์ ์ ์ select์ ์ ๋์์ ์ง์ ํ๋ ๊ฒ์ ๋๋ค.
ํ๋ก์น์ ๋์์ด ํ๋์ธ ๊ฒฝ์ฐ,
๋ ์ด์์ธ ๊ฒฝ์ฐ,
DTO๋ก ์กฐํํ๋ ๊ฒฝ์ฐ์ ๋ํ ๋ฐฉ๋ฒ์ด ๋ชจ๋ ๋ค๋ฅด๊ธฐ์ ํ๋ํ๋ ์์๋ฅผ ๋ํด ์์๊ฐ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๊ทธ์ ์ ์ฐ์ ํ๋ก์ ์ ์ ์ฌ์ฉํ ๋ ๊ฐ์ฅ ๊ถ์ฅ๋๋ ๋ฐฉ๋ฒ์ธ @QueryProjection์ ์ฌ์ฉ๋ฒ๋ถํฐ ์์๋ณด๊ฒ ์ต๋๋ค.
@QueryProjection
@QueryProjection์ ์์ฑ์๋ฅผ ํตํด DTO๋ฅผ ์กฐํํ๋ ๋ฐฉ๋ฒ๊ณผ ํจ๊ป ์ฌ์ฉ๋ฉ๋๋ค.
DTO์ ์์ฑ์์ @QueryProjection์ ๋ถ์ฌ์ฃผ์ด์ผ ํฉ๋๋ค.
data class MemberDtoQueryProjection @QueryProjection constructor(
val username: String,
val age: Int,
)
์ดํ ๋น๋ ์ DTO๊ฐ Qํ์ผ๋ก ์์ฑ๋ฉ๋๋ค.
์์ฑ๋ Qํ์ ์ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
/**
* ํ๋ก์ ์
- @QueryProjection ์ฌ์ฉ
*
* ๋จ์ - Qํด๋์ค ์์ฑ
* - DTO๊ฐ QueryDSL์ ๋ํ ์์กด์ฑ์ ๊ฐ์ง
*/
@Test
fun testQueryProjection() {
val fetch = query
.select(QMemberDtoQueryProjection(member.username, member.age))
.from(member)
.fetch()
fetch.forEach { println(it) }
}
@QueryProjection์ ์ฌ์ฉํ๋ฉด ์ปดํ์ผ ์์ ํ์ ์ฒดํฌ๋ฅผ ํ ์ ์์ด ์ดํ ์๊ฐํ ์ฌ๋ฌ ๋ฐฉ๋ฒ๋ค๋ณด๋ค ์์ ํ ๋ฐฉ๋ฒ์ ๋๋ค.
๊ทธ๋ฌ๋ DTO์ QueryDSL ์ด๋ ธํ ์ด์ ์ ์ ์งํด์ผ ํ๋ ์ ๊ณผ(์์กด์ฑ์ ์ถ๊ฐ), DTO๊น์ง Qํ์ผ์ ์์ฑํด์ผ ํ๋ ๋จ์ ์ด ์์ต๋๋ค.
ํ๋ก์ ์ ๋์์ด ํ๋์ธ ๊ฒฝ์ฐ
๋์์ด ํ๋๋ผ๋ฉด ํ์ ์ ๋ช ํํ๊ฒ ์ง์ ํ์ฌ ๊ฒฐ๊ณผ๊ฐ์ผ๋ก ๋ฐํ๋ฐ์ ์ ์์ต๋๋ค.
@Test
fun testSimpleProjection() {
//given
val fetch: List<String> = query
.select(member.username)
.from(member)
.fetch()
//when
fetch.forEach { println(it) }
}
member์ username์ String์ด๋ฏ๋ก ์์ ๊ฐ์ด String ํ์ ์ผ๋ก ๋ฐ๋ก ์กฐํํ ์ ์์ต๋๋ค.
ํ๋ก์ ์ ๋์์ด ๋ ์ด์
ํ๋ก์ ์ ๋์์ด ๋ ์ด์์ธ ๊ฒฝ์ฐ์๋ Tuple์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ์กฐํํ ์ ์์ต๋๋ค.
@Test
fun testTupleProjection() {
val fetch = query
.select(member.username, member.age)
.from(member)
.fetch()
fetch.forEach {
println("username : ${it.get(member.username)}")
println("age : ${it.get(member.age)}")
}
}
์ฐธ๊ณ ๋ก Tuple์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ํ๋ก์ ์ ํ ๋ ์ฌ์ฉํ๋ Expression์ ๊ทธ๋๋ก ์ฌ์ฉํ์ฌ get์ ์ธ์๋ก ๋๊ฒจ์ฃผ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
DTO๋ก ์กฐํ
Projections๋ฅผ ์ฌ์ฉํฉ๋๋ค.
QueryDSL์ 3๊ฐ์ง์ ๋ฐฉ๋ฒ์ ํตํด DTO๋ก ์กฐํํ ์ ์๋๋ก ์ง์ํฉ๋๋ค.
- ํ๋กํผํฐ ์ ๊ทผ (Setter) : setter์ ๊ธฐ๋ณธ ์์ฑ์ ํ์
- ํ๋ ์ง์ ์ ๊ทผ : ๊ธฐ๋ณธ ์์ฑ์ ํ์
- ์์ฑ์ ์ฌ์ฉ : ํ์ ์ด ์ผ์นํ๋ ์์ฑ์ ํ์
1. ํ๋กํผํฐ ์ ๊ทผ๋ฒ - Setter ์ฌ์ฉ
Projections.bean()์ ์ฌ์ฉํฉ๋๋ค.
data class MemberDto(
var username: String? = null,
var age: Int? = null,
)
/**
* ํ๋ก์ ์
- DTO ์กฐํ
*
* ํ๋กํผํฐ(์ธํฐ), ํ๋ ์ง์ , ์์ฑ์ ๋ชจ๋
*
* ์ธํฐ - bean - ๊ธฐ๋ณธ ์์ฑ์ ํ์
*/
@Test
fun testDTOProjection_setter() {
//given
val fetch = query
.select(Projections.bean(
MemberDto::class.java,
member.username,
member.age))
.from(member)
.fetch()
//when
fetch.forEach {
println(it)
}
}
2. ํ๋ ์ง์ ์ ๊ทผ
Projections.fields()์ ์ฌ์ฉํฉ๋๋ค.
data class MemberDto(
var username: String? = null,
var age: Int? = null,
)
/**
* ํ๋ก์ ์
- DTO ์กฐํ
*
* ํ๋กํผํฐ, ํ๋ ์ง์ , ์์ฑ์ ๋ชจ๋
*
* ํ๋ - fields - ๊ธฐ๋ณธ ์์ฑ์ ํ์(getter, setter ์์ด๋ ๋ผ)
*/
@Test
fun testDTOProjection_field() {
//given
val fetch = query
.select(Projections.fields(
MemberDto::class.java,
member.username,
member.age))
.from(member)
.fetch()
//when
fetch.forEach {
println(it)
}
}
DTO์ Entity์ ํ๋๋ช ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ
ExpressionUtils.as(source, alias) : ํ๋๋ ์๋ธ ์ฟผ๋ฆฌ์ ๋ณ์นญ์ ์ ์ฉํ ์ฌ์ฉํฉ๋๋ค.
username.as(alias) : ํ๋์ ๋ณ์นญ์ ์ ์ฉํ ๋ ์ฌ์ฉํฉ๋๋ค.
data class UserDto(
var name: String? = null,
var aage: Int? = null,
)
/**
* ํ๋ก์ ์
- DTO ์กฐํ
*
* fields - ์ ์ฒด ์์ฑ์ ์์ด์ผ ํจ
*
* ๋ณ์นญ์ด ๋ค๋ฅธ ๊ฒฝ์ฐ - as ์ฌ์ฉ
*/
@Test
fun testDTOProjection_field_other_alias() {
//given
val m = QMember("sub")
val fetch = query
.select(Projections.fields(
UserDto::class.java,
member.username.`as`("name"),
ExpressionUtils.`as`(JPAExpressions.select(m.age.max()).from(m), "aage")))
.from(member)
.fetch()
//when
fetch.forEach {
println(it)
}
}
3. ์์ฑ์ ์ฌ์ฉ
Projections.contructor()์ ์ฌ์ฉํฉ๋๋ค.
data class MemberDto(
var username: String? = null,
var age: Int? = null,
)
/**
* ํ๋ก์ ์
- DTO ์กฐํ
*
* ํ๋กํผํฐ, ํ๋ ์ง์ , ์์ฑ์ ๋ชจ๋
*
* ์์ฑ์ - constructor - ์ ์ฒด ์์ฑ์ ์์ด์ผ ํจ
*/
@Test
fun testDTOProjection_constructor() {
//given
val fetch = query
.select(Projections.constructor(
MemberDto::class.java,
member.username,
member.age))
.from(member)
.fetch()
//when
fetch.forEach {
println(it)
}
}
Reference
'๐๏ธ Spring > QueryDsl' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[QueryDLS] ๋์ ์ฟผ๋ฆฌ ์์ฑ๋ฒ (0) | 2021.12.24 |
---|---|
[QueryDSL] ์์์ ๋ฌธ์ ๋ํ๊ธฐ (Expressions.constant, concat) (2) | 2021.12.23 |
[QueryDSL] CASE ๋ฌธ (0) | 2021.12.23 |
[QueryDSL] ์๋ธ ์ฟผ๋ฆฌ (0) | 2021.12.23 |
[QueryDSL] ์กฐ์ธ, ํ์น์กฐ์ธ (0) | 2021.12.23 |