JpaRepository와 CrudRepository의 차이점

JpaRepository와 CrudRepository의 차이점

Category
Published
May 27, 2024
Last updated
Last updated September 7, 2024

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> { }
JpaRepository
import org.springframework.data.repository.CrudRepository; public interface BarRepository extends CrudRepository<Bar, Long> { }
CrudRepository
위와 같이 선언 방식도 똑같지만, 위치한 패키지가 다른 것을 볼 수 있습니다.
notion image

org.springframework.data.repository

notion image
 

org.springframework.data.jpa.repository

notion image
 
위와 같이 CrudRepository가 존재하는 Spring Data Commons는 기본적인 레포지토리를 제공합니다.
반면에 JPARepository가 존재하는 Spring Data JPA는 Spring Data Commons의 여러 인터페이스를 기반으로 상속하여 복잡한 인터페이스를 제공합니다.

상속 관계

notion image
  • 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는 쿼리 메소드 기능을 제공합니다

References