Хранилища данных
Хранилище представляет собой базу данных или любой другой источник данных в приложении.
Подсистема ядра Jmix предоставляет JpaDataStore, которое хранит сущности JPA в реляционной базе данных. Это основной механизм персистентности в приложениях Jmix. Когда в этом руководстве упоминается хранилище данных, всегда имеется в виду JpaDataStore, если явно не указано иное.
Дополнение REST DataStore предоставляет RestDataStore, которое работает с DTO сущностями, сопоставленными с REST API удаленного приложение Jmix. REST хранилище данных имеет некоторые ограничения по сравнению с JPA хранилищем.
Поддерживаемые базы данных
Следующие базы данных поддерживаются в Jmix из коробки:
- 
HSQLDB (in-memory база данных на Java) 
- 
PostgreSQL 
- 
MySQL 5.1+ 
- 
MariaDB 
- 
Microsoft SQL Server 2008+ 
- 
Oracle 
Редактор хранилищ данных в Studio автоматически настраивает свойства подключения и добавляет соответствующий JDBC-драйвер в список зависимостей в build.gradle.
| При использовании MariaDB с Jmix 2.4 - 2.6 понизьте версию Liquibase, добавив следующий код в ваш  Подробнее см. в тикете #3888. | 
Если вам необходимо подключить реляционную базу данных, не поддерживаемую в Jmix из коробки, следуйте инструкциям в разделе Studio: Подключение к неподдерживаемым базам данных.
Нереляционная база данных может быть использована путем создания нестандартного хранилища или напрямую, как описано в руководстве MongoDB Integration in Jmix.
Основное хранилище
При создании нового проекта Jmix в Studio у него есть одно хранилище данных main, подключенное к реляционной базе данных. Параметры подключения указаны в следующих свойствах приложения:
main.datasource.url = jdbc:hsqldb:file:.jmix/hsqldb/demo
main.datasource.username = sa
main.datasource.password =
main.liquibase.change-log = com/company/demo/liquibase/changelog.xml| Используйте возможности управления хранилищами в Studio для настройки подключения к базе данных. | 
Основной класс приложения содержит соответствующее объявление бина JDBC DataSource:
@Bean
@Primary
@ConfigurationProperties("main.datasource")
DataSourceProperties dataSourceProperties() {
    return new DataSourceProperties();
}
@Bean
@Primary
@ConfigurationProperties("main.datasource.hikari")
DataSource dataSource(final DataSourceProperties dataSourceProperties) {
    return dataSourceProperties.initializeDataSourceBuilder().build();
}Все сущности JPA по умолчанию связаны с основным хранилищем данных.
Дополнительные хранилища
Для работы с несколькими базами данных необходимы дополнительные хранилища данных.
| Используйте возможности управления хранилищами в Studio для настройки дополнительных хранилищ данных. | 
У каждого дополнительного хранилища есть уникальное имя, которое указано в списке свойства приложения jmix.core.additional-stores, разделенном запятыми. Параметры подключения к базе данных имеют имя хранилища в качестве префикса. В приведенных ниже примерах настроено дополнительное хранилище locations:
jmix.core.additional-stores = locations,inmem
locations.datasource.url = jdbc:hsqldb:file:.jmix/hsqldb/locations
locations.datasource.username = sa
locations.datasource.password =
locations.liquibase.change-log = com/company/demo/liquibase/locations-changelog.xmlДля каждого дополнительного хранилища Studio создает класс конфигурации Spring и определяет в нем JDBC DataSource и другие необходимые бины:
@Configuration
public class LocationsStoreConfiguration {
    @Bean
    @ConfigurationProperties("locations.datasource")
    DataSourceProperties locationsDataSourceProperties() {
        return new DataSourceProperties();
    }
    @Bean
    @ConfigurationProperties(prefix = "locations.datasource.hikari")
    DataSource locationsDataSource(@Qualifier("locationsDataSourceProperties") DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().build();
    }
    @Bean
    LocalContainerEntityManagerFactoryBean locationsEntityManagerFactory(
            @Qualifier("locationsDataSource") DataSource dataSource,
            JpaVendorAdapter jpaVendorAdapter,
            DbmsSpecifics dbmsSpecifics,
            JmixModules jmixModules,
            Resources resources
    ) {
        return new JmixEntityManagerFactoryBean("locations", dataSource, jpaVendorAdapter, dbmsSpecifics, jmixModules, resources);
    }
    @Bean
    JpaTransactionManager locationsTransactionManager(@Qualifier("locationsEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JmixTransactionManager("locations", entityManagerFactory);
    }
    @Bean("locationsLiquibaseProperties")
    @ConfigurationProperties(prefix = "locations.liquibase")
    public LiquibaseProperties locationsLiquibaseProperties() {
        return new LiquibaseProperties();
    }
    @Bean("locationsLiquibase")
    public SpringLiquibase locationsLiquibase(@Qualifier("locationsDataSource") DataSource dataSource,
                                              @Qualifier("locationsLiquibaseProperties") LiquibaseProperties liquibaseProperties) {
        return JmixLiquibaseCreator.create(dataSource, liquibaseProperties);
    }
}Чтобы связать сущность с дополнительным хранилищем данных, используйте аннотацию @Store на классе сущностей:
@Store(name = "locations")
@JmixEntity
@Table(name = "COUNTRY")
@Entity
public class Country {| Studio добавляет аннотацию @Storeпри выборе дополнительного хранилища данных для сущности в дизайнере сущностей. | 
В приведенном выше примере сущность Country будет храниться в базе данных, подключенной в качестве хранилища данных locations.
Нестандартные хранилища
Нестандартное хранилище данных может помочь вам работать с некоторыми сущностями DTO так же, как и с сущностями JPA – с помощью DataManager. Если сущность DTO связана с нестандартным хранилищем данных, DataManager делегирует операции CRUD этому хранилищу и использует его при поддержке ссылок на DTO из других сущностей.
Давайте рассмотрим процесс создания нестандартного хранилища данных. Представим неперсистентную сущность Metric и хранилище в памяти для нее.
- 
Создайте класс, реализующий интерфейс DataStore. Класс должен быть prototype бином Spring. Приведенный ниже пример демонстрирует примитивную реализацию, которая способна хранить в памяти сущности различных типов.@Component @Scope(BeanDefinition.SCOPE_PROTOTYPE) public class InMemoryStore implements DataStore { // ... }
- 
Создайте класс, реализующий интерфейс StoreDescriptor. Класс должен быть singleton бином Spring и его методgetBeanName()должен возвращать имя бина реализации хранилища данных, созданного на предыдущем шаге:@Component public class InMemoryStoreDescriptor implements StoreDescriptor { @Override public String getBeanName() { return "inMemoryStore"; } @Override public boolean isJpa() { return false; } }
- 
Добавьте имя хранилища данных (в данном случае это inmem) в свойствоjmix.core.additionalStores:jmix.core.additional-stores = locations,inmem
- 
Задайте имя бина StoreDescriptorв свойствеjmix.core.storeDescriptor_<store_name>:jmix.core.store-descriptor_inmem = inMemoryStoreDescriptor
- 
Добавьте к сущности аннотацию @Store:@Store(name = "inmem") (1) @JmixEntity(annotatedPropertiesOnly = true) (2) public class Metric {1 Аннотация @Storeуказывает имя хранилища.2 Подробности см. в описании @JmixEntity. 
- 
Теперь вы можете сохранять и загружать сущность с помощью DataManager, и он будет делегировать операции CRUD нестандартному хранилищу данных:Metric metric = dataManager.create(Metric.class); metric.setName("test"); metric.setValue(10.0); dataManager.save(metric); Metric metric1 = dataManager.load(Id.of(metric)).one();Кроме того, если другая сущность ссылается на Metric, экземплярMetricбудет загружаться автоматически при обращении к ссылочному атрибуту.