→ Specifications, Query By Example은 실무에서 거의 사용되지 않고 QueryDSL로 대체되기 때문에 생략합니다.

Projections


→ 엔티티 대신에 DTO를 편리하게 조회할 때 사용한다.

Case_회원 이름만 조회하고 싶은 경우

  1. 인터페이스 기반 Closed Projections

    public interface UsernameOnly{
    		String getUsername();
    }
    
    public interface MemberRepository ... {
     List<UsernameOnly> findProjectionsByUsername(String username);
    }
    
  2. 인터페이스기반 **Open Projections → SpEL문법 지원**

    public interface UsernameOnly{
    		@Value("#{target.username + ' ' + target.age + ' ' + target.team.name}")
    		String getUsername();
    }
    
  3. 클래스 기반 **Projections → 다음과 같이 인터페이스가 아닌 구체적인 DTO형식도 가능하다. → 생성자의 파라미터 이름으로 매칭한다.**

    public class UsernameOnlyDto {
    
    		private final String username;
    
    		public UsernameOnlyDto(String username) {
    				this.username = username;
    		}
    
    		public String getUsername() {
    				return username;
    		}
    }
    
  4. 동적 **Projections → 아래와 같이 Generic type을 주면, 동적으로 프로젝션 데이터 변경 가능**

    <T> List<T> findProjectionsByUsername(String username, Class<T> type);
    

    사용코드

    List<UsernameOnly> result = memberRepository.findProjectionsByUsername("m1",UsernameOnly.class);
    

중첩 구조 처리

public interface NestedClosedProjection {
    String getUsername();

    TeamInfo getTeam();

    interface TeamInfo {
        String getName();
    }
}
/* 실행 쿼리 */
select
 m.username as col_0_0_,
 t.teamid as col_1_0_,
 t.teamid as teamid1_2_,
 t.name as name2_2_
from
 member m
left outer join
 team t
 on m.teamid=t.teamid
where
 m.username=?

주의

정리