Search
Duplicate

나머지 기능들

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

Projections

→ 엔티티 대신에 DTO를 편리하게 조회할 때 사용한다. Case_회원 이름만 조회하고 싶은 경우

1.
인터페이스 기반 Closed Projections
public interface UsernameOnly{ String getUsername(); } public interface MemberRepository ... { List<UsernameOnly> findProjectionsByUsername(String username); }
Java
복사
조회할 엔티티의 필드를 getter형식으로 지정하면 해당 필드만 선택해서 조회한다.(Projection)
→ 프로퍼티 형식(getter)의 인터페이스를 제공하면, 구현체는 스프링 데이터 JPA가 제공한다.
2.
인터페이스기반 Open Projections → SpEL문법 지원
public interface UsernameOnly{ @Value("#{target.username + ' ' + target.age + ' ' + target.team.name}") String getUsername(); }
Java
복사
SpEL문법을 사용하면, DB에서 엔티티 필드를 모두 조회한 다음 계산한다. →JPQL SELECT 절 최적화가 안된다.
3.
클래스 기반 Projections → 다음과 같이 인터페이스가 아닌 구체적인 DTO형식도 가능하다. → 생성자의 파라미터 이름으로 매칭한다.
public class UsernameOnlyDto { private final String username; public UsernameOnlyDto(String username) { this.username = username; } public String getUsername() { return username; } }
Java
복사
4.
동적 Projections → 아래와 같이 Generic type을 주면, 동적으로 프로젝션 데이터 변경 가능
<T> List<T> findProjectionsByUsername(String username, Class<T> type);
Java
복사
사용코드
List<UsernameOnly> result = memberRepository.findProjectionsByUsername("m1",UsernameOnly.class);
Java
복사

중첩 구조 처리

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=?
Java
복사

주의

프로젝션 대상이 root 엔티티면, JPQL SELECT 절 최적화 가능
프로젝션 대상이 root가 아니면
LEFT OUTER JOIN 처리
모든 필드를 SELECT해서 엔티티로 조회한 다음에 계산

정리

프로젝션 대상이 ROOT 엔티티 일 경우 유용하다.
프로젝션 대상이 ROOT 엔티티 를 넘어가면 JPQL SELECT 최적화가 안된다.
실무에서는 단순한 경우에만 사용한다.

Native Query

→ 가급적 네이티브 쿼리는 사용하지 않는게 좋다. 정말 어쩔수 없을 때 사용. 최신 버전에서는 스프링 데이터 Projections 가 지원되니 이 기능을 사용하도록 하자.

Projections 활용

→ 스프링 데이터 JPA 네이티브 쿼리 + 인터페이스 기반 Projections 활용
@Query(value = "SELECT m.member_id as id, m.username, t.name as teamName " + "FROM member m left join team t", countQuery = "SELECT count(*) from member", nativeQuery = true) Page<MemberProjection> findByNativeProjection(Pageable pageable);
Java
복사

동적 네이티브 쿼리

하이버네이트를 직접 활용한다.
스프링 JdbcTemplate, MyBatis, jooq같은 외부 라이브러리를 사용한다.

ex: 하이버네이트 기능 사용

String sql = "select m.username as username from member m"; List<MemberDto> result = em.createNativeQuery(sql) .setFirstResult(0) .setMaxResults(10) .unwrap(NativeQuery.class) .addScalar("username") .setResultTransformer(Transformers.aliasToBean(MemberDto.class)) .getResultList();
Java
복사