스프링 데이터 JPA는 메서드 이름을 분석해 JPQL 쿼리를 자동 생성 및 실행하는 강력한 기능을 제공. 이를 통해 복잡한 JPQL 작성 없이 간단하게 데이터를 조회할 수 있으며, 밀요에 따라 정적 쿼리도 직접 정의할 수 있다.
1. 순수 JPA에서의 쿼리 메서드 작성
순수 JPA를 사용하면 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();
}
순수 JPA 테스트 코드
@Test
public void findByUsernameAndGreaterThan() {
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);
}
2. 스프링 데이터 JPA
스프링 데이터 JPA는 메서드 이름을 기반으로 쿼리를 자동으로 생성. 같은 조회 기능을 아래와 같이 간단히 구현할 수 있다.
public interface MemberRepository extends JpaRepository<Member, Long> {
List<Member> findByUsernameAndGreaterThan(String username, int age);
}
- 스프링 데이터 JPA는 메서드 이름을 분석해서 JPQL을 생성하고 실행한다.
스프링 데이터 JPA가 제공하는 쿼리 메소드 기능
- 조회: find...By, read...By, query...By, get...By
- 예) findHelloBy(중간에 설명을 위한 단어를 넣어도 무방)
- COUNT: count...By → 반환 타입: long
- 삭제: delete...By, remove...By → 반환 타입: long
- LIMIT: findFirst, findTop
- DISTINCT: findDistinctBy 또는 findMemberDistinctBy
- EXISTS: exists...By → 반환 타입: boolean
- 예) findHelloBy (중간에 설명을 위한 단어를 넣어도 무방)
참고 : 이 기능은 엔티티의 필드명이 변경되면 인터페이스에 정의한 메서드 이름도 꼭 함께 변경해야 한다. 그렇지 않으면 애플리케이션을 시작하는 시점에 오류가 발생한다.
3. @Query, 리포지토리 메서드에 쿼리 정의하기
복잡한 쿼리를 정의해야 할 경우 @Query를 사용한다. 아래는 이름과 나이를 기준으로 회원을 조회하는 예
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);
}
- 정적 쿼리의 장점
- 문법 오류를 애플리케이션 실행 시점에 감지 기능
- 복잡한 조건이 많을 때 메서드 이름이 길어지는 문제를 해결
- 실무에서는 메서드 이름으로 쿼리 생성 기능은 파라미터가 증가하면 메서드 이름이 매우 지저분해지므로 @Query 기능을 자주 사용하게 된다.
4. DTO 로 직접 조회하기
JPA는 DTO를 조회할 때 new 명령어를 사용한다. 생성자가 매칭되는 DTO 클래스를 작성해야함.
DTO 정의
@Data
public class MemberDto {
private Long id;
private String username;
private String teamName;
public MemberDto(Long id, String username, String teamName) {
this.id = id;
this.username = username;
this.teamName = teamName;
}
}
DTO 조회 쿼리
@Query("select new study.datajpa.dto.memberdto(m.id, m.username, t.name) " +
"from member m join m.team t")
List<MemberDto> findMemberDto();
주의! DTO로 직접 조회 하려면 JPA의 new 명령어를 사용해야 한다. 그리고 다음과 같이 생성자가 맞는 DTO가 필요하다.
파라미터 바인딩
파라미터는 이름 기반으로 바인딩하는 것을 권장
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select m from Member m where m.username = :name")
Member findMember(@Param("name") String username);
}
컬렉션 파라미터 바인딩
Collection 타입으로 in절 지원
@Query("select m from Member m where m.username in :names")
List<Member> findByNames(@Param("names") List<String> names);
6. 단순 값 조회
값 하나를 조회하거나 DTO가 아닌 기본 자료형으로 값을 가져올 수 있다.
@Query("select m.username from Member m")
List<String> findUsernameList();
추가 팁: 실무 활용
- 메서드 이름 기반 쿼리는 간단한 조회에 유용하지만, 복잡한 조건이나 연산이 필요한 경우 @Query를 선호
- DTO 조회는 new 키워드로 생성자를 명확히 지정해야 함.
- 컬렉션 바인딩은 여러 파라미터를 처리할 때 유용.
'Back-End > JPA' 카테고리의 다른 글
| Spring Data JPA : 벌크성 수정 쿼리와 엔티티 그래프 (2) | 2024.12.18 |
|---|---|
| Spring Data Jpa : 페이징과 정렬 (1) | 2024.12.18 |
| 프록시와 연관관계 관리(JPA) (0) | 2024.12.17 |
| 상속관계 매핑(JPA) (0) | 2024.12.17 |
| JPA 연관관계 Mapping(2) (0) | 2024.12.14 |