Репозитории данных
Репозитории данных Spring Data предоставляют полезную абстракцию для работы с сущностями, особенно для реализации бизнес-логики.
Репозитории данных Jmix построены на базе Spring Data, но внутри используют DataManager. Это позволяет использовать удобный интерфейс репозиториев и при этом иметь полную поддержку продвинутых возможностей доступа к данным Jmix, таких как события сущностей, ссылки между сущностями из разных хранилищ, проверки доступа к данным и т.п.
| В текущей версии 2.6 API репозиториев данных Jmix помечен как экспериментальный. В следующем функциональном релизе в него могут быть внесены незначительные изменения и API станет стабильным. | 
Работа с репозиториями данных
Вы можете создать репозиторий данных Jmix двумя способами: используя Мастер создания репозитория данных или следуя шагам, описанным ниже.
- 
Создайте интерфейс, унаследованный от JmixDataRepository. Используйте класс сущности и класс идентификатора сущности в качестве параметров типаJmixDataRepository. Например:public interface CustomerRepository extends JmixDataRepository<Customer, UUID> { }
- 
Создайте новый класс конфигурации Spring в базовом пакете и добавьте ему аннотацию @EnableJmixDataRepositories:package com.company.demo; import io.jmix.core.repository.EnableJmixDataRepositories; import org.springframework.context.annotation.Configuration; @EnableJmixDataRepositories @Configuration public class JmixDataRepositoryConfiguration { }Jmix проинициализирует все репозитории данных, расположенные внутри и ниже базового пакета приложения или дополнения. Если требуется более тонкая настройка поиска репозиториев, используйте атрибуты аннотации basePackages,excludeFiltersиincludeFilters.
- 
Инжектируйте репозиторий в бины Spring или UI-контроллеры с помощью аннотации @Autowired:@Autowired private CustomerRepository customerRepository;
Особенности JmixDataRepository
Интерфейс JmixDataRepository расширяет стандартный интейфейс PagingAndSortingRepository из Spring Data. Он предоставляет несколько собственных методов, учитывающих специфику Jmix:
- 
Методы загрузки, такие как findById()илиfindAll(), могут принимать фетч-план.
- 
Метод create()создает новый экземпляр сущности.
- 
Метод getById()с обязательным результатом загружает сущность по идентификатору и выбрасывает исключение, если сущность не найдена.
- 
Метод getDataManager()возвращаетDataManagerдля использования в методах по умолчанию.
- 
Метод save()сохраняет предоставленную сущность и возвращает сохраненный экземпляр, загруженный с указанным планом выборки. Метод принимает сущность для сохранения и план выборки, который будет применен при перезагрузке сохраненной сущности. Сущность не может бытьnull, а план выборки должен быть применим к сущности.
JmixDataRepositoryContext
Методы загрузки репозиториев, унаследованных от JmixDataRepository, поддерживают дополнительный аргумент типа JmixDataRepositoryContext. Это позволяет передавать параметры фильтрации, пейджинга и сортировки, собранные в объект LoadContext из UI-компонентов. В результате все функции компонентов genericFilter, simplePagination и dataGrid будут полноценно работать с репозиториями данных.
Используйте статический метод JmixDataRepositoryUtils.buildRepositoryContext() для конвертации LoadContext в JmixDataRepositoryContext.
Security Constraints
Вы можете добавить аннотацию io.jmix.core.repository.ApplyConstraints своему репозиторию данных. Если значение аннотации равно false, репозиторий использует UnconstrainedDataManager вместо DataManager. Значение аннотации по умолчанию - true.
Аннотация @ApplyConstraints может быть использована не только для всего класса, но и для отдельных методов, чтобы игнорировать или, наоборот, включить ограничения только для них.
public interface OrderRepository extends JmixDataRepository<Order, UUID> {
    @Override
    Iterable<Order> findAll(Sort sort, @Nullable FetchPlan fetchPlan);
    @Override
    @ApplyConstraints(false)
    Iterable<Order> findAll(FetchPlan fetchPlan);
    @ApplyConstraints(false)
    List<Order> findByIdNotNull();
}В приведенном выше примере @ApplyConstraints(false) применяется только к двум методам, и для них будет использоваться UnconstrainedDataManager.
В приведенном ниже примере ограничения отключены для всего класса, но включены точечно для отдельных методов:
@ApplyConstraints(false)
public interface ProductRepository extends JmixDataRepository<Product, UUID> {
    @Override
    Iterable<Product> findAll(Sort sort, @Nullable FetchPlan fetchPlan);
    @Override
    @ApplyConstraints
    Page<Product> findAll(Pageable pageable);
    List<Product> getByIdNotNull();
    @ApplyConstraints
    List<Product> searchByIdNotNull();
    List<Product> searchById(UUID id);
}Методы findAll() и searchByIdNotNull() будут использовать обычный DataManager, в то время как все остальные методы будут использовать UnconstrainedDataManager.
Annotations
Следующие аннотации можно использовать на кастомных методах запросов:
- 
@io.jmix.core.repository.Queryзадает строку JPQL аналогично аннотации@Queryв Spring Data JPA.
- 
@io.jmix.core.repository.FetchPlanзадает фетч-план для загрузки данных.
- 
@io.jmix.core.repository.QueryHintsи@jakarta.persistence.QueryHintпозволяют вам указать хинты для отключения мягкого удаления и использования кэша запросов.
| Если имя метода/запроса и параметры метода имеют разные значения для плана выборки и хинтов, то окончательные значения выбираются на основе приоритета, от самого высокого к самому низкому. FetchPlan: 
 Hints: 
 Для хинтов с одинаковым ключом значение из источника с более высоким приоритетом переопределит значение из источника с более низким приоритетом. Разные ключи будут объединены. | 
Примеры методов запросов
Репозитории данных Jmix поддерживают стандартную возможность Spring Data выводить запрос из имени метода, например:
List<Customer> findByEmailContainingIgnoreCase(String emailPart);Аналогично Spring Data JPA, JPQL-запрос можно явно задать с помощью аннотации @io.jmix.core.repository.Query:
@Query("select c from sample_Customer c where c.email like :email")
List<Customer> findCustomersByEmail(@Param("email") String emailPart);Методы запросов могут принимать объект Pageable для постраничной загрузки и сортировки:
Page<Customer> findByEmailContainingIgnoreCase(String emailPart, Pageable pageable);Другой специально обрабатываемый параметр, который можно использовать в методах запросов - фетч-план:
List<Customer> findByEmailContainingIgnoreCase(String emailPart, FetchPlan fetchPlan);Разделяемый фетч-план можно задавать по имени в аннотации @io.jmix.core.repository.FetchPlan:
@FetchPlan("customer-minimal")
List<Customer> findByEmail(String email);Кэшируемый запрос:
@QueryHints(@QueryHint(name = PersistenceHints.CACHEABLE, value = "true"))
List<Customer> findByEmail(String email);