Spring Data JPA - 쿼리 메서드 기능
스프링 데이터 JPA가 제공하는 쿼리 메서드 기능을 살펴보자.
쿼리 메서드 기능은 여러가지 방법으로 사용할 수 있다.
- 메서드 이름으로 쿼리 생성
- 메서드 이름으로 JPA NamedQuery 호출
- @Query 사용해서 Repository Interface에 쿼리 정의
1. 메서드 이름으로 쿼리 생성
Member 엔티티가 있다고 생각할 때, 이름과 나이를 기준으로 회원을 조회하자.
순수 JPA Repository로 구현하면 위와같이 메서드를 만들어서 써야한다.
하지만 저번 블로그글 때 사용했던 스프링데이터JPA를 쓰면 간단해진다.
스프링 데이터 JPA는 메서드 이름을 분석해서 JPQL을 생성하고 실행하기 때문에 스프링 데이터 JPA 공식 문서를 참고해서 사용하자.
😈 주의할 점
이 기능은 엔티티의 필드명이 변경되면 인텊이스에 정의한 메서드 이름도 꼭 변경하자!!!
그렇지 않으면 애플리케이션 시작 시점에 오류가 발생!!! (애플리케이션 로딩 시점에 오류 인지할 수 있는 부분은 장점)
📝 메서드 이름으로 쿼리 만드는 방법 예시
메서드 이름은 subject(주제)와 predicate(조건자) 부분으로 나뉜다.
첫 번째 부분인 subject에는 추가 표현이 포함될 수 있다.
생성할 쿼리에 쿼리 결과를 제한하는 키워드를 사용하지 않으면 그냥 설명하는 것으로 간주된다.
즉 , findABCDEBy... 이런식이면 find는 제한키워드로 찾는다이고, 그 뒤 By까지의 ABCDE 텍스트는 설명하는 것으로 간주된다.
그래서 findListBy... , find텍스트설명By... 이런식으로 만들 수 있는 것이다.
그렇다면 query method subject keywords(쿼리 메서드 주제 키워드)는 무엇이 있을까?
위 공식 문서를 참고하면 나오지만 간단하게 적어보자면
- find...By , read...By , get...By , query...By , search...By , stream...By
- exists...By
- count...By
- delete...By , remove...By
- ...First<number>... , ...Top<number>...
- ...Distinct...
이렇게 사용할 수 있다.
query method predicate keywords and modifiers(쿼리 메서드 조건자 키워드 및 수정자)에는 다음것들이 있다.
- AND
- OR
- AFTER
- BEFORE
- BETWEEN 등
위의 것들을 참고해서 아무거나 만들어보자.
findMemberDistinctBy : 중복없이 전체 조회 (By 뒤에 아무것도 안적으면 전체 조회)
existsMemberByName : 파라미터로 받은 값이 Name 컬럼에 존재하는지 boolean 타입으로 반환
2. JPA NamedQuery
스프링 데이터 JPA는 메서드 이름으로 JPA Named 쿼리를 호출하는 기능이 있다.
말 그대로 쿼리에 이름을 부여해서 사용하는 방법이다.
어노테이션 또는 XML에 쿼리를 정의할 수 있다.
이렇게 엔티티에 정의하고 나서 아래와 같이 Repository에서 Named 쿼리를 호출해야한다.
또는 스프링 데이터 JPA를 사용하면 아래와 같이 메서드 이름만으로 Named 쿼리를 호출할 수 있다.
위 스프링 데이터 JPA는 선언한 "도메인 클래스 + . + 메서드 이름"으로 Named 쿼리를 찾아 실행한다.
따라서 @Query를 생략해도 메서드 이름만으로도 Named 쿼리를 호출할 수 있다.
만약 Named 쿼리가 없으면 메서드 이름으로 첫번째 방법인 쿼리 생성 전략을 사용한다.
바로 위 메서드의 파라미터에 @Param이 있는데 이것은 이름기반 파라미터를 바인딩할 때 사용하는 어노테이션이다.
😈 스프링 데이터 JPA를 사용하면 실무에서 NamedQuery를 직접 등록해 사용하는것 보다 @Query를 사용한다.
왜냐하면 메서드 이름으로 쿼리 생성 기능은 파라미터가 증가하면 메서드 이름이 길어지기에 @Query 기능을 사용하게 된다.
3. @Query 사용해서 Repository 메서드에 쿼리 정의
이것은 아까 두번째 방법에서 사용했던 @Query 어노테이션을 사용한다.
실행할 메서드에 정적 쿼리를 직접 작성하기에 이름 없는 Named 쿼리라고 할 수 있다.
이것 역시 애플리케이션 실행 시점에 문법 오류를 발견할 수 있다.
이것은 JPQL로 쓴 거라 SQL과 비슷하지만 다르다.
SQL은 테이블 대상으로 쿼리를 한 것이고, JPQL은 객체를 대상으로 쿼리를 한 것이다.
동적 쿼리 부분은 queryDSL로 사용하는게 가장 깔끔하고 유지보수성이 좋다고 한다.
나만의 결론
간단한 것일때는 1번째 방법인 메서드 이름으로 쿼리 생성
좀 더 파라미터나 조건이 복잡해지면 3번째 방법으로 쿼리를 작성하는 것이 좋다.
위는 정적 쿼리의 경우이고, 동적 쿼리의 경우에는 queryDSL을 사용해보자.