JPA란?
Java Persistence API의 약자다.
자바에서 관계형 데이터베이스를 사용하는 데 필요한 기능을 제공하는 ORM기술이다.
Spring Data JPA란?
위에서 언급한 JPA를 쉽게 사용할 수 있도록 스프링에서 제공하는 프레임워크다.
쿼리 생성, 페이징, 정렬, 캐싱 등의 기능을 제공해준다. 위에서 JPA가 ORM기술이라고 했는데 Spring Data JPA는 다양한 데이터베이스와의 호환을 도와준다.
공식 문서에서는 아래 예제가 먼저 우리를 반겨주고 있다.
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity); (1)
Optional<T> findById(ID primaryKey); (2)
Iterable<T> findAll(); (3)
long count(); (4)
void delete(T entity); (5)
boolean existsById(ID primaryKey); (6)
// … more functionality omitted.
}
뭔가 이상한 점이 느껴질 수 있다. jpa를 사용해봤다면 일반적으로 JpaRepository를 상속받아서 사용했을텐데 그냥 Repository를 상속받고 있다. 하지만 이건 우리가 지금까지 편하게 사용을 했을 뿐 근본적으로는 Repository에서 부터 시작한다.
이렇게 되면 우리는 JpaRepository를 상속받아 사용함으로써 모든 기능을 사용할 수 있는 것이 된다.
근데 보다보면 재미있는 어노테이션이 하나 존재한다.
@NoRepositoryBean
해당 인터페이스는 스프링 빈으로 등록하지 않는 어노테이션이다.
왜 이게 있을까 2가지로 추측을 해보았다.
1. 공통 인터페이스의 문제
우리는 다양한 곳에서 해당 어노테이션을 호출할 것이다. 그러면 그때마다 스프링 빈으로 만들고 등록을 한다면? 상당히 꼬일 가능성이 높다.
2. 책임의 문제
어찌되었건 이건 DB와 관련이 있는 어노테이션이다. 사용자가 원하는 시점에 빈을 생성하도록 책임을 넘겨주는 역할
뭐 일단 이렇게 한다고 하자. 아무튼 인터페이스의 명명규칙을 이용해 쉽게 데이터에 접근할 수 있다.
인터페이스의 정의
JpaRepository를 정의하기 위해서는 2가지 데이터 타입을 입력해주어야한다.
공식 문서 상에는 T, ID로 되어있다.
T는 왜 T인지 모르겠지만 보통 제네릭에서 데이터 타입을 T로 말하긴한다. ID는 말 그대로 ID값을 의미한다.
그러면 T와 ID에 뭐가 들어가냐.
T에는 우리가 데이터를 읽고 쓰고 하기 위한 테이블(도메인)의 데이터 타입이 들어가야한다.
ID에는 해당 테이블의 ID의 타입이 들어가야한다.
그러면 T에 정의하기 위해 어떻게 해야하는가.
아무 데이터나 막 넣지는 말고 어노테이션이 붙은 클래스를 넣어야한다.
interface PersonRepository extends Repository<Person, Long> { … }
@Entity
class Person { … }
interface UserRepository extends Repository<User, Long> { … }
@Document
class User { … }
갑자기 Document라는 어노테이션이 튀어나오긴 했는데 당황하지 말자. 위에서 언급한 것 처럼 Spring Data JPA는 다양한 DB와 호환이 가능하다. @Document가 붙으면 MongoDB에 호환이 된다는 것을 알려준다.
@Entity는 RDBMS에서만 사용이 가능하며(대표적으로 MariaDB) 우리가 익히 알고있듯 MongoDB는 NoSQL 데이터베이스라 @Document가 붙어야한다.
이제 등록을 할 줄 알게 되었다. 그러면 실제 조회를 편하게 하기 위해 어떻게 해야할까.
스프링 공식문서에서는 다양한 쿼리 예제를 제공하고 있다.
interface PersonRepository extends Repository<Person, Long> {
List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
// Enables the distinct flag for the query
List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);
// Enabling ignoring case for an individual property
List<Person> findByLastnameIgnoreCase(String lastname);
// Enabling ignoring case for all suitable properties
List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);
// Enabling static ORDER BY for a query
List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
}
이걸 하나 하나 다 설명하면 좀 머리가 아픈데.. 다음에 한번 다뤄보도록 하자.
'JAVA > spring' 카테고리의 다른 글
spring + slack webhook 연동하기 (0) | 2023.07.12 |
---|---|
SpringBoot 3.x 버전에서 junit5 를 사용해서 테스트하는데 왜 RunWith가 먹히지 않고 필요가 없는가? (0) | 2023.07.07 |
spring method 요청에 대해 핸들링하기 (0) | 2023.03.13 |
spring boot 최소한으로 logging 설정하기(logback을 곁들인) (0) | 2023.03.12 |
Flyway Placeholder사용(application.yml / properties 파일 읽기) (0) | 2023.02.26 |