ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ 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 ํ•„์š” ์—†์Œ

     

    Querydsl - ๋ ˆํผ๋Ÿฐ์Šค ๋ฌธ์„œ

    Querydsl์€ JPA, JDO, Mongodb ๋ชจ๋“ˆ์—์„œ ์ฝ”๋“œ ์ƒ์„ฑ์„ ์œ„ํ•ด ์ž๋ฐ”6์˜ APT ์–ด๋…ธํ…Œ์ด์…˜ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ์ ˆ์—์„œ๋Š” ์ฝ”๋“œ ์ƒ์„ฑ์„ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ์„ค์ • ์˜ต์…˜๊ณผ APT์— ๋Œ€ํ•œ ๋Œ€์•ˆ์„ ์„ค๋ช…ํ•œ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ Query

    querydsl.com

     

    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€

Designed by Tistory.