TL;DR개요차이점패키지상속 관계PagingAndSortingRepository, ListPagingAndSortingRepositoryCrudRepository, ListCrudRepositoryQueryByExampleExecutorJpaRepositoryJpaRespository vs CrudRepositoryReferences
TL;DR
- JpaRepository는 CrudRepository, ListPagingAndSortingRepository 등을 상속한다
- org.springframework.data.jpa는 org.springframework.data에 의존성을 가진다
- JpaRepository는 CrudRepository의 CRUD 기능을 포함하며, 페이징 및 정렬, 쿼리 메소드 기능등이 추가되어 있다
개요
해당 글의 내용은 Spring Boot 3를 기준으로 합니다. Spring Boot 2에서는 일부 차이가 존재합니다
스프링에서 레포지토리를 구축할 때 보통 JpaRepository를 구현해서 사용합니다. 그렇다면 CrudRepository 라는 구현체를 들어보셨나요? CrudRepository는 이름에서 볼 수 있듯, CRUD 기능을 제공합니다.
이렇게 보면 JpaRespotory와 CrudRepository는 똑같은 CRUD를 제공하는데, 어떤 차이를 가지는지 알아보겠습니다.
차이점
패키지
import org.springframework.data.jpa.repository.JpaRepository; @Repository public interface FooRepository extends JpaRepository<Foo, Long> { }
import org.springframework.data.repository.CrudRepository; public interface BarRepository extends CrudRepository<Bar, Long> { }
위와 같이 선언 방식도 똑같지만, 위치한 패키지가 다른 것을 볼 수 있습니다.
위와 같이 CrudRepository가 존재하는 Spring Data Commons는 기본적인 레포지토리를 제공합니다.
반면에 JPARepository가 존재하는 Spring Data JPA는 Spring Data Commons의 여러 인터페이스를 기반으로 상속하여 복잡한 인터페이스를 제공합니다.
상속 관계
- JpaRespository는 ListCrudRepository, ListPagingAndSortingRepository와 QueryByExampleExecutor를 상속받습니다.
- ListCrudRepository는 CrudRepository를 상속받습니다.
- ListPagingAndSortingRepository는 PagingAndSortingRepository를 상속받습니다.
PagingAndSortingRepository, ListPagingAndSortingRepository
@NoRepositoryBean public interface PagingAndSortingRepository<T, ID> extends Repository<T, ID> { Iterable<T> findAll(Sort sort); Page<T> findAll(Pageable pageable); } @NoRepositoryBean public interface ListPagingAndSortingRepository<T, ID> extends PagingAndSortingRepository<T, ID> { List<T> findAll(Sort sort); }
PagingAndSortingRepository는 sort, pagination 기능을 가진 findAll() 메소드를 제공합니다.
이를 확장한 ListPagingAndSortingRepository는 엔티티의 Iterable대신 List를 반환합니다.
Iterable과 List의 차이는?
Iterable은 forEach 사용이 가능하여 연속적인 데이터의 순회를 위한 자료형으로 자바의 최상위 인터페이스 중 하나입니다
List는 Collection을 상속하고, Collection은 Iterable를 상속합니다. List는 Iterable보다 다양한 기능을 제공합니다
CrudRepository, ListCrudRepository
@NoRepositoryBean public interface CrudRepository<T, ID> extends Repository<T, ID> { <S extends T> S save(S entity); <S extends T> Iterable<S> saveAll(Iterable<S> entities); Optional<T> findById(ID id); boolean existsById(ID id); Iterable<T> findAll(); Iterable<T> findAllById(Iterable<ID> ids); long count(); void deleteById(ID id); void delete(T entity); void deleteAllById(Iterable<? extends ID> ids); void deleteAll(Iterable<? extends T> entities); void deleteAll(); } @NoRepositoryBean public interface ListCrudRepository<T, ID> extends CrudRepository<T, ID> { <S extends T> List<S> saveAll(Iterable<S> entities); List<T> findAll(); List<T> findAllById(Iterable<ID> ids); }
CrudRepository에는 저희가 자주 사용하는 기본 CRUD에 대한 메소드가 존재합니다. 목록을 반환할 때 Iterable형을 사용하지만, ListCrudRepository에서 List형을 반환하게 오버라이딩 됩니다.
QueryByExampleExecutor
public interface QueryByExampleExecutor<T> { <S extends T> Optional<S> findOne(Example<S> example); <S extends T> Iterable<S> findAll(Example<S> example); <S extends T> Iterable<S> findAll(Example<S> example, Sort sort); <S extends T> Page<S> findAll(Example<S> example, Pageable pageable); <S extends T> long count(Example<S> example); <S extends T> boolean exists(Example<S> example); <S extends T, R> R findBy(Example<S> example, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction); }
QueryByExampleExecutor 인터페이스를 상속하기 때문에, JpaRepository는 쿼리 메소드 기능을 사용할 수 있다.
쿼리 메소드란? 메소드 이름을 기반으로 자동으로 데이터베이스 쿼리를 생성/실행 하는 기능을 말한다
예시: findByName(), findByAgeLessThan() 등
Docs: https://docs.spring.io/spring-data/jpa/reference/jpa/query-methods.html
JpaRepository
@NoRepositoryBean public interface JpaRepository<T, ID> extends ListCrudRepository<T, ID>, ListPagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> { void flush(); <S extends T> S saveAndFlush(S entity); <S extends T> List<S> saveAllAndFlush(Iterable<S> entities); void deleteAllInBatch(Iterable<T> entities); void deleteAllByIdInBatch(Iterable<ID> ids); void deleteAllInBatch(); T getReferenceById(ID id); @Override <S extends T> List<S> findAll(Example<S> example); @Override <S extends T> List<S> findAll(Example<S> example, Sort sort); }
JpaRespository vs CrudRepository
- JpaRespository는 Iterator를 반환하는 CrudRepository와 달리 List를 반환하기에 사용이 더 편리합니다
- JpaRespository는 pagination과 정렬 기능을 추가적으로 제공합니다
- JPARespository는 쿼리 메소드 기능을 제공합니다