반응형
250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
Tags
- 그룹함수
- 스프링 데이터 JPA
- 컬렉션 조회 최적화
- 데이터베이스
- TCP/IP
- INDEX SCAN
- 친절한 SQL 튜닝
- JPA
- fetch join
- @MappedSuperclass
- 스프링 컨테이너
- 정렬
- SQL
- SQL 튜닝
- Spring data JPA
- DTO
- 데이터모델링
- Spring
- 값 타입
- 페이징
- 성능최적화
- 오라클
- querydsl
- 스프링
- JPQL
- 엔티티
- 자바의 정석
- 서브쿼리
- 페치조인
- index
Archives
- Today
- Total
nu_s
[Spring Data JPA] 쿼리 메서드 🍀 본문
728x90
반응형
쿼리메서드
- 이전에 쿼리 메서드에 대해 간단하게 언급했었는데, 조금 더 깊게 들어가보도록 하자
- 만약 도메인에 특화되어 있거나, 검색 조건이 들어간 쿼리는 어떻게 해결해야 할까?
- 이 방법을 해결하는 3가지 방법이 있다.
- 메서드 이름으로 쿼리 생성하기
- 메서드 이름으로 JPA NamedQuery 호출하기
- @Query 어노테이션을 사용해서 리포지토리 인터페이스에 쿼리 직접 정의하기
1. 메서드 이름으로 쿼리 생성
- 메서드 이름을 분석해서 JPQL 쿼리를 실행한다.
- 이름과 나이를 기준으로 회원을 조회하려면 어떻게 해야할까?
JPA 리포지토리
public List<Member> findByUsernameAndAgeGreaterThan(String username, int age) {
return em.createQuery("select m from Member m where m.username = :username and m.age > :age")
.setParameter("username", username)
.setParameter("age", age)
.getResultList();
}
테스트
@Test
public void findByUsernameAndAgeGreaterThan() {
Member m1 = new Member("AAA", 10);
Member m2 = new Member("AAA", 20);
memberJpaRepository.save(m1);
memberJpaRepository.save(m2);
List<Member> result = memberJpaRepository.findByUsernameAndAgeGreaterThan("AAA", 15);
assertThat(result.get(0).getUsername()).isEqualTo("AAA");
assertThat(result.get(0).getAge()).isEqualTo(20);
assertThat(result.size()).isEqualTo(1);
}
- 위의 코드처럼 쿼리를 만들고 테스트를 돌려보면 간단하게 통과한다.
- 그러나 우리는 스프링 데이터 JPA를 통해 코드를 더 간단히 만드는 방법을 배웠다.
스프링 데이터 JPA
public interface MemberRepository extends JpaRepository<Member, Long> {
List<Member> findByUsernameAndAgeGreaterThan(String username, int age);
}
- 이렇게 구현부 없이 인터페이스로 생성해준 뒤 같은 테스트 코드를 실행해도 통과한다.
- 단순한 쿼리도 아닌데 왜 구현부가 없이도 잘 동작하는걸까?
- 이유는 바로 메서드 이름에 있다.
https://docs.spring.io/spring-data/jpa/reference/jpa/query-methods.html
JPA Query Methods :: Spring Data JPA
As of Spring Data JPA release 1.4, we support the usage of restricted SpEL template expressions in manually defined queries that are defined with @Query. Upon the query being run, these expressions are evaluated against a predefined set of variables. Sprin
docs.spring.io
- 링크를 따라 들어가보면 메서드의 이름과 쿼리의 관계가 나와있다.
- 이를 참고하여 코드를 만들면 된다.
스프링 데이터 JPA가 제공하는 쿼리 메서드 기능
- 조회
- find...By
- read...By
- query...By
- get...By
- COUNT : count...By
- EXISTS : exists...By
- 삭제
- delete...By
- remove...By
- DISTINCT
- findDistinct
- findMemberDistinctBy
- LIMIT
- findFirst3
- findFirst
- findTop
- findTop3
장점
- 별도로 쿼리를 작성해주지 않아도 이름만 잘 작성하면 편리하게 사용할 수 있다.
단점
- 파라미터가 많아질수록 이름이 점점 길어진다는 단점이 있다.
- 쿼리가 간단할 때만 사용하자
2. JPA NamedQuery
@Entity
@NamedQuery(
name = "Member.findByUsername",
query = "select m from Member m where m.username = :username"
)
public class Member {
...
}
- 두번째 방법은 NamedQuery이다.
- 엔티티에 @NamedQuery 어노테이션을 사용해서 사용할 쿼리와 그 쿼리의 이름을 지정해준다.
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query(name = "Member.findByUsername") //생략 가능
List<Member> findByUsername(@Param("username") String username);
}
- 리포지토리에서 @Query 어노테이션을 통해 불러올 쿼리의 이름을 적어준다.
- @Param으로 파라미터 이름을 설정해준다.
- 여기서 @Query는 생략이 가능하다.
- 만약 생략했다면 우선순위에 따라 처리한다.
- 먼저 메서드 이름과 같은 NamedQuery를 Member에서 탐색한다.
- 없다면 처음에 설명한 방식인 메서드 이름으로 쿼리를 생성한다.
장점
- 오타가 났어도 애플리케이션 실행 시점에 문법 오류를 발견해준다.
그러나 실무에서 잘 사용하지 않으니, 이런 방법이 있다는 것만 알아두자.
3. @Query
3-1. 리포지토리 메서드에 쿼리 정의하기
- @Query 어노테이션을 사용하여 쿼리를 직접 작성하는 방법이다.
- 실행할 메서드에 정적 쿼리를 직접 작성하므로 이름 없는 NamedQuery라고 할 수 있다.
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select m from Member m where m.username = :username and m.age = :age")
List<Member> findUser(@Param("username") String username, @Param("age") int age);
}
장점
- JPA NamedQuery처럼 애플리케이션 실행 시점에 문법 오류를 발견해준다.
- 파라미터가 많고 쿼리가 복잡한 경우 이 방식을 사용하자.
3-2. 값 조회하기
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select m.username from Member m")
List<String> findUsernameList();
}
- 값 타입은 이런 방식으로 조회할 수 있다.
- @Embedded 타입도 가능하다.
3-3. DTO 조회하기
@Data
@AllArgsConstructor
public class MemberDto {
private Long id;
private String username;
private String teamName;
}
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) from Member m join m.team t")
List<MemberDto> findMemberDto();
}
- DTO로 조회할 땐 이렇게 조회하면 된다.
- 단, new 명령어를 사용해야 한다.
출처 : 인프런 실전! 스프링 데이터 JPA
728x90
반응형
'Spring Data JPA' 카테고리의 다른 글
[Spring Data JPA] @EntityGraph 🍀 (0) | 2023.12.03 |
---|---|
[Spring Data JPA] 벌크성 수정 쿼리 🍀 (0) | 2023.12.02 |
[Spring Data JPA] 페이징 & 정렬 🍀 (0) | 2023.12.01 |
[Spring Data JPA] 파라미터 바인딩 & 반환 타입 🍀 (0) | 2023.11.29 |
[Spring Data JPA] 스프링 데이터 JPA 🍀 (0) | 2023.11.20 |