[Spring Data JPA] 네이티브 쿼리 (Native Query)
[Spring Data JPA] 네이티브 쿼리 (Native Query)
네이티브 쿼리란?
- JPA 표준 JPQL 대신 데이터베이스 고유의 SQL 쿼리를 사용하여 엔티티를 조회하는 기능
- 가급적이면 사용하지 않는 게 좋다.
- 정말 어쩔 수 없는 경우에만 사용해야 한다.
특징
- JPQL 제약 극복
- JPQL로 표현하기 어려운 복잡한 쿼리를 작성할 수 있습니다.
- 데이터베이스 최적화
- 데이터베이스 특화 기능을 활용하여 쿼리 성능을 향상시킬 수 있습니다.
- 유연성
- 다양한 데이터베이스 플랫폼을 지원한다.
문제점
- Sort 파라미터를 통한 정렬이 정상 동작하지 않을 수 있다.
- 믿지 말고 직접 처리하는 것이 좋다.
- JPQL처럼 애플리케이션 로딩 시점에 문법 확인할 수 없다.
- 동적 쿼리가 불가능하다.
- 하이버네이트를 직접 활용하면 가능은 하다.
- 그냥 JdbcTemplate 또는 myBatis를 사용하는 것이 좋다.
사용 방법
- 리포지토리에 네이티브 쿼리를 사용할 메소드를 생성한다.
public interface MemberRepository extends JpaRepository<Member, Long> {
Member findByNativeQuery(String username);
}- 1번에서 생성한 메소드에
@Query어노테이션을 추가하고, 쿼리를 작성한 뒤,nativeQuery = true속성을 명시한다.
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query(value = "select * from member where username = ?", nativeQuery = true)
Member findByNativeQuery(String username);
}- 필요한 곳에서 사용한다.
@Test
public void nativeQuery() {
//given
Team teamA = new Team("teamA");
em.persist(teamA);
Member m1 = new Member("m1", 0, teamA);
Member m2 = new Member("m2", 0, teamA);
em.persist(m1);
em.persist(m2);
em.flush();
em.clear();
//when
Member result = memberRepository.findByNativeQuery("m1");
System.out.println("result = " + result);
}- 페이징도 적용할 수 있다.
@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);@Test
public void nativeQuery() {
//given
Team teamA = new Team("teamA");
em.persist(teamA);
Member m1 = new Member("m1", 0, teamA);
Member m2 = new Member("m2", 0, teamA);
em.persist(m1);
em.persist(m2);
em.flush();
em.clear();
//when
Page<MemberProjection> result = memberRepository.findByNativeProjection(PageRequest.of(0, 10));
List<MemberProjection> content = result.getContent();
for (MemberProjection memberProjection : content) {
System.out.println("memberProjection = " + memberProjection.getUsername() + " / " + memberProjection.getTeamName());
}
}주의 사항
- JPQL은 위치 기반 파리미터를 1부터 시작하지만 네이티브 쿼리는 0부터 시작한다.
- 네이티브 쿼리로 엔티티가 아닌 DTO로 조회하기는 JdbcTemplate 또는 myBatis를 사용하는 것이 좋다.
- 네이티브 쿼리는 데이터베이스 플랫폼에 종속적이기 때문에, 플랫폼이 변경되면 쿼리를 수정해야 된다.
- JPQL보다 더 복잡하고 오류 가능성이 높다.
- DTO 대신에 프로젝션으로 조회할 수 있다.
출처
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.