먼저 Spring Data JPA를 활용하는 방식은 EntityManager의 활용 방식 차이이다.
이전에 배웠던 JPA의 Entity, @Id 등 Annotation에 대한 것은 완전히 동일하게 Spring Data JPA에서 활용할 수 있는 것이다.
그렇다면 Spring Data JPA는 일반 JPA와 어떤 점이 다르기에 그토록 사용을 추천하는 것일까?
우리는 이전에 일반 JPA에서는 EntityManager를 먼저 상속받은 이후 em.remove, em.find 등을 통해 활용함을 알 수 있었다.
하지만 JPA는 이 EntityManager를 상속받는 과정마저 없애버린 것이다.
실제로 MyBatis에서는 SqlSession을 활용하지만 이 SqlSession을 주입받는 과정은 생략된다. 하지만 JPA에서는 EntityMangerFactory를 전역에서 활용할 수 있도록 설정해 줘야 하는 것은 물론 EntityManagerFactory를 통해 EntityManager를 생성하고 이를 주입받는 것까지 모두 수행되어야 한다.
Spring Data JPA는 이런 귀찮은 작업을 아예 없애버린 것이다.
Spring Data JPA에서는 "JpaRepsitory"라는 특수한 인터페이스를 상속하여 새로운 인터페이스를 만들어주기만 하면 아무런 언급 없이 EntityManager를 활용할 수 있으며 직접 Query를 구현하지 않더라도 JPA측에서 알아서 Query를 구현해주는 것이다.
물론 JPA도 자동으로 Query를 구성해주지만 JpaRepository를 활용하면 자동으로 만들어주는 Query를 조금 더 자세히 짤 수 있는데, 아래에서 설명하겠지만 WHERE 절 등에 추가하는 조건 등을 정해진 Naming Rule에 의해 짜주기만 하면 알아서 이를 인지하고 Query를 만들어주는 것이다.
그렇다면 Spring Data JPA의 여러 Naming Rule에 대해 알아보자
메서드 시작 부분 | 메서드 종류 |
---|---|
findBy | 쿼리를 요청하는 메서드 : 결과값이 객체 |
countBy | 쿼리 결과의 레코드 수를 요청하는 메서드 : 결과값이 정수형 |
사용 가능 키워드 | 예시 | 설명 |
---|---|---|
And | findByEmailAndUserId(String email, String userId) | 여러 필드를 And 탐색 |
Or | findByEmailOrUserId(String email, String userId) | 여러 필드를 Or 탐색 |
Between | findByCreatedAtBetween(Date fromDate, Date toDate) | 필드 두 값 사이에 있는 항목 탐색 |
LessThan/GreaterThan | findByAgeGraterThanEqual(int age) | 작은/큰 항목 탐색 |
GreaterThanEqual | findByAgeGraterThanEqual(int age) | 크거나 같은 항목 탐색 |
Like | findByNameLike(String name) | Like '~~'로 결과값 탐색 |
IsNull | findByJobIsNull() | null인 항목 탐색 |
OrderBy | findByEmailOrderByNameAsc(String email) | 검색 결과 정렬 |
public interface PostsRepository extends JpaRepository<Posts, Long> {
@Query("SELECT p FROM Posts p ORDER BY p.id DESC")
List<Posts> findAllDesc();
@Query("SELECT p FROM Posts p where p.title=?1")
Posts findByTitle(String title);
Posts findByTitle(String title);
}
여기에서 재밌는 점은 아마 @Query가 아닐까 싶다.
@Query를 활용하면 내가 원하는 Query를 입력할 수 있고, Query에 따른 결과를 Entity로 바꿔주어 반환해준다.
여기에서 Query는 "JPQL"이라고 하는데, 이는 나중에 설명할 기회가 있을 것이다.
그리고 findByTitle 메서드에 대한 Query를 잘 확인해보자.
findByTitle 같은 경우는 입력값을 받는다. 그런데 나중에 실제로 활용할 떄는 입력값을 여러개 받아야 될 수도 있을 것이다.
이 경우 ?1, ?2 등을 활용하여 "몇 번째 데이터를" Query문에 넣어 수행해줘야하는지 알려준다.
"?x"로 입력할 경우 x번째 Input으로 들어온 값을 Query문에 넣어 실행해야 함을 알 수 있다.
(물론 findByTitle 같은 경우는 굳이 @Query를 활용하지 않아도 Naming Rule에 부합하므로 알아서 만들어주겠지만, 예시를 통해 일부러 @Query를 활용해보았다)
2번째로 봐야하는 점은 "public interface"라는 점이다.
MyBatis에서도 Mapper같은 경우에도 "인터페이스"였다. 마찬가지로 Spring Data도 JPA로 생성해줘야 JPA측에서 알아서 이 interface를 구현체로 만들어서 실제로 활용할 수 있게 되는 것이다.
3번째로 봐야할 점은 상속하는 "JpaRepository<Posts, Long>"이다.
여기에서 Posts는 Entity를 의미하며 Long은 "식별자 필드의 자료형"을 의미한다.
꼭 기억하자. JpaRepository와 같이 입력해야 하는 것은 "<Entity, 식별자 필드의 자료형>"이라는 점!!!