Ответ
Spring Data JPA предоставляет несколько способов для расширения стандартного CRUD-функционала сложной бизнес-логикой.
1. Пользовательские запросы с @Query (JPQL / Нативный SQL):
Подходит для сложных, но выразимых в виде одного запроса операций.
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE " +
"(:departmentId IS NULL OR u.department.id = :departmentId) AND " +
"u.registrationDate BETWEEN :startDate AND :endDate")
List<User> findComplexUsers(@Param("departmentId") Long departmentId,
@Param("startDate") LocalDate start,
@Param("endDate") LocalDate end);
}
2. Кастомный репозиторий (Рекомендуемый способ для сложной логики):
Позволяет использовать EntityManager, JdbcTemplate, Criteria API и любую Java-логику.
Шаг 1: Создайте интерфейс для кастомных методов.
public interface UserRepositoryCustom {
List<User> findUsersWithComplexBusinessLogic(SearchFilter filter);
void performMultiStepUpdate(Long userId, UpdateCommand command);
}
Шаг 2: Реализуйте этот интерфейс. Имя класса реализации должно заканчиваться на Impl (по умолчанию).
public class UserRepositoryImpl implements UserRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<User> findUsersWithComplexBusinessLogic(SearchFilter filter) {
// 1. Создание CriteriaQuery для динамического построения запроса
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> root = query.from(User.class);
// ... сложная логика построения предикатов
// 2. Выполнение нативного SQL, если нужно
// Query nativeQuery = entityManager.createNativeQuery("...");
// 3. Любые Java-манипуляции с результатами
return entityManager.createQuery(query).getResultList();
}
}
Шаг 3: Расширьте основной репозиторий.
public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
// Стандартные методы Spring Data JPA + кастомные методы
}
Теперь можно использовать:
userRepository.findUsersWithComplexBusinessLogic(filter);
userRepository.save(user); // Стандартный метод
Этот подход сохраняет всю мощь Spring Data JPA, добавляя гибкость для сложных сценариев.