-
[ Querydsl ] ํ๋ก์ ์ (Projections)๊ณผ ๊ฒฐ๊ณผ๋ฐํ (ํ๋กํผํฐ์ ๊ทผ, ํ๋์ง์ ์ ๊ทผ, ์์ฑ์ ์ฌ์ฉ)JPA 2022. 3. 28. 14:00๋ฐ์ํ
ํ๋ก์ ์ (Projections) ?
Querydsl์ ์ด์ฉํด entity์ ์ฒด๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ด ์๋๋ผ ์กฐํ ๋์์ ์ง์ ํด ์ํ๋ ๊ฐ๋ง ์กฐํํ๋ ๊ฒ์ ๋งํ๋ค.
๊ธฐ๋ณธ
1. ํ๋ก์ ์ ๋์์ด ํ๋์ผ ๋
List<String> result = queryFactory .select(member.username) .from(member) .fetch();
ํ๋ก์ ์ ๋์์ด ํ๋์ผ๊ฒฝ์ฐ ์์ฒ๋ผ ํ์ ์ ๋ช ํํ๊ฒ ์ง์ ํ๋ฉด ๋๋ค.
2. ํ๋ก์ ์ ๋์์ด ๋๊ฐ ์ด์์ผ ๊ฒฝ์ฐ
List<Tuple> result = queryFactory .select(member.username, member.age) .from(member) .fetch(); for (Tuple tuple : result) { String username = tuple.get(member.username); Integer age = tuple.get(member.age); System.out.println("username=" + username); System.out.println("age=" + age); }
ํ๋ก์ ์ ๋์์ด ๋๊ฐ ์ด์์ผ ๊ฒฝ์ฐ ๋ช ํํ ํ์ ์ ์ง์ ํ ์ ์๊ธฐ ๋๋ฌธ์ ํํ์ด๋ DTO๋ก ๊ฐ์ ์กฐํํ ์ ์๋ค.
ํ์ง๋ง ํํ๋ก ๊ฐ์ ๊ฐ์ ธ์ค๋ ๊ฒฝ์ฐ๋ Querydsl์ ์ข ์์ ์ด๊ณ , Model ๊ฐ์ฒด๋ฅผ ๋ก์ง์์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๊ฐ์ ๋ฌธ์ ๋ฅผ ๊ฐ์ง๊ณ ์๊ธฐ์ ์ต๋ํ ์ฌ์ฉ์ ํผํ๊ณ Repository์์๋ง ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค. ๋ง์ฝ Repository ๋ฐ๊นฅ์ผ๋ก ๋๊ฐ ๋ DTO๋ก ๋ณํํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค.
DTO ์กฐํ
1. ์์ JPA์์ DTO ์กฐํ
MemberDto
package study.querydsl.dto; import lombok.Data; @Data public class MemberDto { private String username; private int age; public MemberDto() { } public MemberDto(String username, int age) { this.username = username; this.age = age; } }
์์ JPA์์ DTO ์กฐํ ์ฝ๋
List<MemberDto> result = em.createQuery( "select new study.querydsl.dto.MemberDto(m.username, m.age)" + "from Member m", MemberDto.class) .getResultList();
์์ JPA์์ DTO๋ฅผ ์กฐํํ ๋๋ new ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ๋๋ฐ ์ด ๊ฒฝ์ฐ ์์ฑ์ ๋ฐฉ์๋ง ์ง์ํ๋ฉฐ, DTO์ package์ด๋ฆ์ ๋ค ์ ์ด์ค์ผํ๊ธฐ ๋๋ฌธ์ ์ฝ๋๊ฐ ์ง์ ๋ถํ๋ค.
์ด๋ฅผ ๊ทน๋ณตํ๊ธฐ ์ํด Querydsl๋ก ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ๋ฐ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ค.
Querydsl ๋น ์์ฑ(Bean population)
๊ฒฐ๊ณผ๋ฅผ DTO๋ก ๋ฐํํ ๋ ์ฌ์ฉํ๋ฉฐ,
1) ํ๋กํผํฐ ์ ๊ทผ 2) ํ๋ ์ง์ ์ ๊ทผ 3) ์์ฑ์ ์ฌ์ฉ ์ ์ธ ๊ฐ์ง ๋ฐฉ์์ด ์๋ค.
1. ํ๋กํผํฐ ์ ๊ทผ
List<MemberDto> result = queryFactory .select(Projections.bean(MemberDto.class, member.username, member.age)) .from(member) .fetch();
Projections.bean
setter(bean)๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ธ์ ์ ํด์ฃผ๋ฉฐ ๊ธฐ๋ณธ ์์ฑ์๊ฐ ๋ฌด์กฐ๊ฑด ํ์ํ๋ค.
(Constructor ๋ง๋ค์ด์ฃผ๊ฑฐ๋ ๋กฌ๋ณต์ฐ๋ฉด @NoArgsContructor ์ฌ์ฉํ์ธ์ !)2. ํ๋ ์ง์ ์ ๊ทผ
List<MemberDto> result = queryFactory .select(Projections.fields(MemberDto.class, member.username, member.age)) .from(member) .fetch();
Projections.fields
ํ๋์ ๊ฐ์ ๋ฑ ๊ฝ์์ฃผ๊ธฐ ๋๋ฌธ์ setter์ ๊ธฐ๋ณธ์์ฑ์๊ฐ ํ์์์ต๋๋ค.2-1. ๋ณ์นญ์ด ๋ค๋ฅผ ๋
package study.querydsl.dto; import lombok.Data; @Data public class UserDto { private String name; private int age; }
List<UserDto> fetch = queryFactory .select(Projections.fields(UserDto.class, member.username.as("name"), ExpressionUtils.as( ) ).from(member) .fetch();
ํ๋กํผํฐ๋ ํ๋ ์ ๊ทผ ์์ฑ ๋ฐฉ์์์ ์ด๋ฆ์ด ๋ค๋ฅผ ๋ ์๋์ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ํด๊ฒฐํ ์ ์๋ค.
1) ExpressionUtils.as(sourse, alias) : ํ๋, ์๋ธ ์ฟผ๋ฆฌ์ ๋ณ์นญ ์ ์ฉ
2) username.as("memberName") : ํ๋์ ๋ณ์นญ ์ ์ฉ๋๋ถ๋ถ์ ๊ฐ๋ ์ฑ๋๋ฌธ์ as๋ฅผ ์ฐ๋๋ฐ ์๋ธ์ฟผ๋ฆฌ์ ๊ฒฝ์ฐ ๋ฌด์กฐ๊ฑด ExpressionUtils.as ๋ฅผ ์จ์ผํ๋ค.
3. ์์ฑ์ ์ฌ์ฉ
List<MemberDto> result = queryFactory .select(Projections.constructor(MemberDto.class, member.username, member.age)) .from(member) .fetch() }
Projections.constructor
๊ฐ์ ๋๊ธธ ๋์์ฑ์์ ์์๊ฐ ๋ง์์ผ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ฉฐ, @AllArgsConstructor ํ์, setter๊ฐ ํ์ ์๋ค.
์์ฑ์ ๋ฐฉ์์ @QueryProjection๊น์ง ์ง์ํด์ค๋ค.@QueryProjection ํ์ฉ
List<MemberDto> result = queryFactory .select(new QMemberDto(member.username, member.age)) .from(member) .fetch();
@QueryProjection ์ด๋ ธํ ์ด์ ์ ๋ฌ์์ฃผ๊ณ , compileQuerydsl์ ์คํํด์ฃผ๋ฉด DTO๋ Qํ์ผ๋ก ์์ฑ์ ํด์ค๋ค.
Contructor๋ ์ปดํ์ผ ์ค๋ฅ๋ฅผ ์ก์ง ๋ชปํ๊ณ ๋ฐํ์ ์ค๋ฅ๊ฐ ์ผ์ด๋๊ธฐ์ ์ ์ ๊ฐ ์ฝ๋๋ฅผ ์คํํ๋ ์๊ฐ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ ์ ์์ง๋ง,
QueryProjection์ ์ปดํ์ผ๋ฌ๋ก ํ์ ์ ์ฒดํฌํ ์ ์์ผ๋ฏ๋ก ๊ฐ์ฅ ์์ ํ ๋ฐฉ๋ฒ์ด๋ค.
ํ์ง๋ง DTO์ QueryDSL ์ด๋ ธํ ์ด์ ์ ์ ์งํด์ผ ํ๊ธฐ์ QueryDSL์ ์ข ์์ ์ธ ์ ๊ณผ DTO๊น์ง Qํ์ผ์ ์์ฑํด์ผ ํ๋ ๋จ์ ์ด ์๋ค.
์ ๋ฆฌ
- Property: setter ์ฌ์ฉ, ๊ธฐ๋ณธ ์์ฑ์ ์ฌ์ฉ
- Field: setter ํ์ ์์, ๊ธฐ๋ณธ ์์ฑ์ ํ์ ์์, ํ๋์ ๋งคํ
- Constructor: @AllArgsConstructor ํ์, setter ํ์ ์์
๋ฐ์ํ'JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ Querydsl ] ๋์ ์ฟผ๋ฆฌ ๋ง๋ค๊ธฐ(BooleanExpression, BooleanBuilder) (0) 2022.03.22 [ JPA ] ๋ณตํฉํค(composite key) ๋งคํ (@EmbeddedId) (0) 2022.02.21