
네이티브 쿼리
- 가급적 네이티브 쿼리는 사용하지 않는게 좋음, 정말 어쩔 수 없을 때 사용
- 최근에 나온 궁극의 방법 스프링 데이터 Projections 활용
- 페이징 지원
- 반환 타입
- Object[]
- Tuple
- DTO(스프링 데이터 인터페이스 Projections 지원)
- 제약
- Sort 파라미터를 통한 정렬이 정상 동작하지 않을 수 있음(믿지 말고 직접 처리)
- JPQL처럼 애플리케이션 로딩 시점에 문법 확인 불가
- 동적 쿼리 불가
@Query(value = "select * from member where username = ?", nativeQuery = true)
Member findByNativeQuery(String username);
Member result = memberRepository.findByNativeQuery("m1");
System.out.println(result);
- JPQL은 위치 기반 파리미터를 1부터 시작하지만 네이티브 SQL은 0부터 시작
- 네이티브 SQL을 엔티티가 아닌 DTO로 변환은 하려면
- DTO 대신 JPA TUPLE 조회
- DTO 대신 MAP 조회
- @SqlResultSetMapping 복잡
- Hibernate ResultTransformer를 사용해야함 복잡
- 네이티브 SQL을 DTO로 조회할 때는 JdbcTemplate or myBatis 권장
Projections 활용
public interface MemberProjection {
Long getId();
String getUsername();
String getTeamName();
}
@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> findByNativeProjections(Pageable pageable);
Page<MemberProjection> result = memberRepository.findByNativeProjections(PageRequest.of(0, 10));
List<MemberProjection> content = result.getContent();
for (MemberProjection memberProjection : content) {
System.out.println(memberProjection.getId());
System.out.println(memberProjection.getUsername());
System.out.println(memberProjection.getTeamName());
}
동적 네이티브 쿼리
- 하이버네이트를 직접 활용
- 스프링 JdbcTemplate, myBatis, jooq같은 외부 라이브러리 사용
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();
}