Spring Data JPA

Violet_Evgadn·2023년 4월 24일
0

DB연동

목록 보기
22/22
post-custom-banner

Spring Data JPA

먼저 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에 대해 알아보자


Spring Data JPA Naming Rule

Query의 종류(INSERT, DELETE, SELECT)를 결정하는 Name

  • save(Entity 객체)
    • Input Entity를 저장하는 Insert 구문 수행
  • findAll()
    • DB Table에 저장된 전체 데이터를 List 형식으로 불러옴
  • count()
    • DB Table에 저장된 전체 데이터의 개수를 반환
  • delete(Entity 객체)
    • Entity 객체와 동일한 Data를 삭제함
    • 이전에도 말했듯 JPA는 @Id, 즉 식별자 값을 통해 Entity를 구별한다. 따라서 식별자 값이 같은 Data가 삭제될 것이다. 따라서 delete를 활용하기보다는 deleteById로 PK값을 통해 Record를 삭제하는 것을 더 추천한다
  • findById(식별자 값)
    • Table에서 동일한 식별자를 가지고 있는 데이터를 찾아 반환
    • 식별자 1개만 Input으로 입력 가능하므로 식별자의 정의에 따라 Entity 1개만 반환할 것이다
  • deleteById(식별자 값)
    • Table에서 동일한 식별자를 가지고 있는 데이터 삭제
  • saveAll(List)
    • List에 존재하는 모든 Entity들을 저장하는 메서드
  • removeAll(List<식별자 자료형>)
    • 먼저 List에 "식별자 자료형"이 들어간다는 점을 잘 인지하자
    • List에 포함된 식별자를 가지고 있는 Tuple들을 DB에서 삭제시킴
  • findAllById(List<식별자 자료형>)
    • List에는 찾고 싶은 Data의 식별자 값이 저장되어 있음
    • Entity 전체를 가져오기 떄문에 당연히 List로 결과값을 받아야 할 것이다.
  • getOne(id)
    • 해당 식별자를 가지는 Entity가 있는 것이 확정일 경우 사용됨

표로 정리하는 Naming Rule

  • 메서드 시작 부분
메서드 시작 부분메서드 종류
findBy쿼리를 요청하는 메서드 : 결과값이 객체
countBy쿼리 결과의 레코드 수를 요청하는 메서드 : 결과값이 정수형
  • 메서드 시작 부분
사용 가능 키워드예시설명
AndfindByEmailAndUserId(String email, String userId)여러 필드를 And 탐색
OrfindByEmailOrUserId(String email, String userId)여러 필드를 Or 탐색
BetweenfindByCreatedAtBetween(Date fromDate, Date toDate)필드 두 값 사이에 있는 항목 탐색
LessThan/GreaterThanfindByAgeGraterThanEqual(int age)작은/큰 항목 탐색
GreaterThanEqualfindByAgeGraterThanEqual(int age)크거나 같은 항목 탐색
LikefindByNameLike(String name)Like '~~'로 결과값 탐색
IsNullfindByJobIsNull()null인 항목 탐색
OrderByfindByEmailOrderByNameAsc(String email)검색 결과 정렬
  • 위의 예시의 경우, Entity에 email, userId, createdAt, age, name, job의 필드변수가 존재해야 함

Spring Data JPA를 활용한 예시

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, 식별자 필드의 자료형>"이라는 점!!!

profile
혹시 틀린 내용이 있다면 언제든 말씀해주세요!
post-custom-banner

0개의 댓글