public interface MemberRepository extends JpaRepository<Member, Long> {
@Query(value = "select * from member where username = ?", nativeQuery = true)
Member findByNativeQuery(String username);
}
class MemberRepositoryTest {
@Test
void nativeQuery() {
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();
Member result = memberRepository.findByNativeQuery("m1");
}
}
select *
from member
where username = 'm1';
조회하려는 필드를 select 절에 다 적어줘야 해서 불편하다.
JPQL처럼 애플리케이션 로딩 시점에 문법을 확인하는 것이 불가하다.
동적 쿼리를 쓸 수 없다.
반환 타입이 제한되어 있다.
Sort 파라미터를 통한 정렬이 정상 동작 하지 않을 수도 있다.
믿지 말고 직접 처리하자.
JPQL은 위치 기반 파라미터를 1부터 시작하지만 SQL은 0부터 시작한다.
Projections 활용
스프링 데이터 JPA 네이티브 쿼리와 인터페이스 기반 Projections를 활용할 수 있다.
public interface MemberProjection {
Long getId();
String getUsername();
String getTeamUsername();
}
public interface MemberRepository extends JpaRepository<Member, Long> {
@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);
}
class MemberRepositoryTest {
@Test
void nativeQuery() {
...
// 인덱스가 0부터 시작하므로 0으로 조회한다.
Page<MemberProjection> result = memberRepository.findByNativeProjection(PageRequest.of(0, 10));
}
}
SELECT m.member_id as id, m.username, t.name as teamName
FROM member m
left join team t limit 10;
SELECT count(*)
from member;
동적 네이티브 쿼리
class Example {
public static void main(String[] args) {
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();
}
}
하이버네이트를 직접 활용한다.
스프링 JdbcTemplate, myBatis, jooq 같은 외부 라이브러리를 사용하는걸 추천한다.