Core concepts
2024. 10. 19. 17:40ㆍSpring Boot/Spring Data JPA
Repository 인터페이스
- 중심 인터페이스: Spring Data 리포지토리 추상화의 중심 인터페이스는
Repository
입니다. 이 인터페이스는 관리할 도메인 클래스와 도메인 클래스의 identifier 타입을 제네릭 타입 파라미터로 받습니다. 기본적으로 이 인터페이스는 마커 인터페이스로 사용되며, 작업할 타입을 캡처하고 이를 확장하는 인터페이스를 발견하는 데 도움을 줍니다. - 도메인 객체: Spring Data는 도메인 타입을 엔티티로 간주하며, 보다 구체적으로 집합체(aggregate)로 설명합니다. 따라서 문서 전반에 걸쳐 "엔티티"라는 용어가 사용되며, 이는 "도메인 타입"이나 "집합체"와 상호 교환할 수 있습니다.
- 도메인 주도 설계(DDD): 도메인 객체는 DDD의 관점에서 정의됩니다. 도메인 객체는 identifier를 가지고 있으며, 특정 패턴으로 데이터에 접근할 때 이 identifier를 참조해야 합니다. identifier를 참조하는 것은 리포지토리 및 쿼리 메서드를 다룰 때 더 의미 있게 됩니다.
CrudRepository 인터페이스
CrudRepository
는 관리되는 엔티티 클래스에 대한 고급 CRUD 기능을 제공합니다.
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)
// ... 더 많은 기능 생략됨.
}
- save(S entity): 주어진 엔티티를 저장합니다. (새로운 엔티티는 삽입되고, 기존 엔티티는 업데이트됨)
- findById(ID primaryKey): 주어진 ID로 식별되는 엔티티를 리턴합니다.
- findAll(): 모든 엔티티를 리턴합니다.
- count(): 현재 저장된 엔티티의 수를 리턴합니다.
- delete(T entity): 주어진 엔티티를 삭제합니다.
- existsById(ID primaryKey): 주어진 ID를 가진 엔티티가 존재하는지 여부를 나타냅니다.
CRUD 메서드
CrudRepository
인터페이스에 선언된 메서드는 일반적으로 CRUD 메서드라고 불립니다.
ListCrudRepository
ListCrudRepository
는CrudRepository
와 동일한 메서드를 제공하지만, 리턴 타입이List
인 반면CrudRepository
는Iterable
을 리합니다.
주의 사항
- 리포지토리 인터페이스는
findById(ID identifier)
와 같은 몇 가지 예약된 메서드를 포함합니다. 이 메서드는 도메인 타입의 identifier 속성을 목표로 하며, 속성 이름과 관계없이 동작합니다. - 만약 식별자를 참조하는 속성이
Id
라는 이름이 아닐 경우,@Query
애노테이션을 사용하여 커스텀 쿼리를 제공할 수 있습니다. 그러나 이렇게 하면 혼란스러울 수 있으며, ID 타입과 Id 속성의 타입이 다를 경우에는 더 많은 제약을 받을 수 있으므로 이러한 경로를 피하는 것이 좋습니다.
JpaRepository 및 MongoRepository
JpaRepository
또는MongoRepository
와 같은 특정 영속성 기술에 대한 추상화도 제공됩니다. 이러한 인터페이스는CrudRepository
를 확장하며, 기본적인 CRUD 기능 외에 특정 영속 기술의 기능을 추가로 노출합니다.
PagingAndSortingRepository 인터페이스
PagingAndSortingRepository
와ListPagingAndSortingRepository
는 엔티티에 대한 페이지 접근을 쉽게 하기 위해 추가적인 메서드를 제공합니다.
public interface PagingAndSortingRepository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
findAll(Sort sort)
: 주어진 정렬 기준에 따라 모든 엔티티를 리턴합니다.findAll(Pageable pageable)
: 주어진 페이지 요청에 따라 엔티티를 페이지 단위로 리합니다.
주의 사항
- 확장 인터페이스는 실제 저장소 모듈에 의해 지원됩니다. 따라서 이 문서에서 설명하는 일반적인 체계와는 별개로, 사용하려는 인터페이스가 사용 중인 저장소 모듈에서 지원되는지 확인해야 합니다.
예제: 페이지 접근
사용자(User) 엔티티에 대해 페이지 크기가 20인 두 번째 페이지에 접근하려면 다음과 같이 할 수 있습니다:
PagingAndSortingRepository<User, Long> repository = // ... bean에 접근
Page<User> users = repository.findAll(PageRequest.of(1, 20));
ListPagingAndSortingRepository
는 동일한 메서드를 제공하지만, 리턴 타입이 List
인 반면 PagingAndSortingRepository
는 Iterable
을 리합니다.
쿼리 메서드
- 쿼리 메서드에 대한 파생 쿼리도 가능합니다. 다음은 파생된 카운트 쿼리의 인터페이스 정의입니다.
파생된 카운트 쿼리
interface UserRepository extends CrudRepository<User, Long> {
long countByLastname(String lastname);
}
파생된 삭제 쿼리
interface UserRepository extends CrudRepository<User, Long> {
long deleteByLastname(String lastname);
List<User> removeByLastname(String lastname);
}
countByLastname(String lastname)
: 주어진 성(lastname)을 가진 사용자 수를 리턴합니다.deleteByLastname(String lastname)
: 주어진 성을 가진 사용자를 삭제하고 삭제된 사용자 수를 리턴합니다.removeByLastname(String lastname)
: 주어진 성을 가진 사용자를 삭제하고 삭제된 사용자 목록을 리턴합니다.
Spring Data 리포지토리의 기본 구조와 사용법을 이해하는 것은 애플리케이션 개발 시 데이터에 접근하고 조작하는 데 큰 도움이 됩니다. CrudRepository
, PagingAndSortingRepository
, 그리고 이들 인터페이스의 파생된 메서드들에 대한 이해는 데이터 처리의 유연성과 효율성을 높여줄 것입니다. 이러한 기능들은 데이터베이스와의 상호작용을 단순화하고, 도메인 객체에 대한 CRUD 작업을 손쉽게 수행할 수 있게 도와줍니다.
'Spring Boot > Spring Data JPA' 카테고리의 다른 글
Configuration (3) | 2024.10.19 |
---|---|
Defining Repository Interfaces (0) | 2024.10.19 |
Getting Started (0) | 2024.10.19 |
Query Hint (0) | 2023.06.06 |
Database Index (0) | 2023.06.04 |