Почему в Spring Data столько разных Repository?
Если вы работали со Spring Data JPA, наверняка писали:
public interface UserRepository
extends JpaRepository<User, Long> {
}
Но почему именно JpaRepository?
Ведь есть ещё:
- CrudRepository
- PagingAndSortingRepository
- ListCrudRepository
- ListPagingAndSortingRepository
- JpaRepository
На самом деле между ними есть разница.
CrudRepository - самый базовый вариант, даёт стандартные CRUD-операции:
save()
findById()
findAll()
delete()
existsById()
Если больше ничего не нужно — можно использовать его.
PagingAndSortingRepository
Добавляет работу со страницами и сортировкой:
findAll(Pageable pageable);
findAll(Sort sort);
Например:
Page<User> users =
repository.findAll(
PageRequest.of(0, 20)
);
Получаем первую страницу из 20 пользователей.
JpaRepository
А вот это уже специализированный вариант именно для JPA.
Он включает возможности CRUD и пагинации, а также добавляет JPA-специфичные операции.
Например:
flush();
saveAndFlush();
deleteAllInBatch();
Поэтому для обычного Spring Boot + Hibernate проекта чаще всего встречается именно:
JpaRepository<User, Long>
Но есть интересный момент
Наследование Repository — это не просто вопрос вкуса.
Если вашему сервису нужен только:
findById()
save()
delete()
ему совершенно не обязательно давать огромный интерфейс с десятками методов.
Можно ограничить контракт:
public interface UserRepository
extends Repository<User, Long> {
Optional<User> findById(Long id);
User save(User user);
}
Теперь снаружи доступны только те методы, которые вы сами объявили. Это иногда помогает держать границы слоя доступа к данным под контролем и ещё одна важная вещь Repository не означает:
«Spring сам написал всю бизнес-логику за нас».
Spring Data умеет генерировать реализацию стандартных операций и производных запросов:
List<User> findByLastName(String lastName);
Spring разберёт имя метода и построит запрос, но если запрос сложный:
- JOIN
- GROUP BY
- оконные функции
- сложная фильтрация
это уже не повод создавать метод длиной в 150 символов:
findByUserStatusAndCreatedAtAfterAnd...
Можно использовать @Query, спецификации, Criteria API или вообще перейти на JDBC/native SQL — в зависимости от задачи.
Главная мысль:
JpaRepository — не «обязательный стандарт».
Выбирая Repository, вы фактически выбираете, какие возможности работы с данными будут доступны вашему коду.
Отвечая на вопрос:
«Почему вы наследуетесь именно от JpaRepository, а не от CrudRepository?»
И вот тут уже интересно не назвать интерфейс, а объяснить зачем вашему приложению его возможности.