JPA가 SQL query를 그대로 사용하는 네이티브 쿼리를 지원한다.
하지만
- 가급적 네이티브 쿼리는 사용하지 않는게 좋다.
- 최근에 나온 final 방법 => 스프링 데이터 Projections 활용
스프링 데이터 JPA 기반 네이티브 쿼리
- 페이징 지원
- 반환 타입
- Object[]
- Tuple
- DTO(스프링 데이터 인터페이스 Projections 지원)
제약이 있는데
- Sort 파라미터를 통한 정렬이 정상 동작하지 않을 수 있고
- JPQL처럼 Application loading 시점에 문법 확인이 불가하고
- 동적 쿼리가 불가능하다.
// MemberRepository Interface
@Query(value = "select * from member where username = ?", nativeQuery = true)
Member findByNativeQuery(String username);
test를 돌려보면 sql이 select절 그대로 나가게 된다.
// MemberRepository
@Query(value = "select * from member where username = ?", nativeQuery = true)
Member findByNativeQuery(String username);
// MemberRepositoryTest
@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);
}
select * from member where username = ?
select * from member where username = 'm1';
result = Member(id=2, username=m1, age=0)
아래와 같은 설정을 한번 해보자.
// MemberProjection Interface
package study.datajpa.repository;
public interface MemberProjection {
Long getId();
String getUsername();
String getTeamName();
}
// MemberRepository Interface
@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를 돌리게 되면
// MemberRepositoryTest
@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를 0을 설정을 해주고
Page<MemberProjection> result = memberRepository.findByNativeProjection(PageRequest.of(0, 10));
List<MemberProjection> content = result.getContent();
for (MemberProjection memberProjection : content) {
System.out.println("memberProjection = " + memberProjection.getUsername());
System.out.println("memberProjection = " + memberProjection.getTeamName());
}
}
select
m.member_id as id,
m.username,
t.name as teamName
from
member m
left join
team t limit ? offset ?
memberProjection = m1
memberProjection = teamA
memberProjection = m2
memberProjection = teamA
이렇게 네이티브 쿼리에서 매칭을 해주면
// MembeRepository
@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);
projection 기능을 그대로 써서 네이티브 쿼리에 대한 문제를 심플하게 해결할 수가 있다.
// MemberProjection Interface
package study.datajpa.repository;
public interface MemberProjection {
Long getId();
String getUsername();
String getTeamName();
}
그래도 이거대신에 스프링의 JDBC Template이나 Mybatis를 쓰자!
끝으로 QueryDSL강의까지 계속 달려보자!
<출처 김영한: 실전! 스프링 데이터 JPA >
'Spring > SpringDataJPA' 카테고리의 다른 글
Projections (0) | 2022.04.19 |
---|---|
Query By Example (0) | 2022.04.19 |
Specifications(명세) (0) | 2022.04.19 |
새로운 엔티티를 구별하는 방법 (0) | 2022.04.18 |
스프링 데이터 JPA 구현체 분석 (0) | 2022.04.18 |