Хранилища данных
Хранилище представляет собой базу данных или любой другой источник данных в приложении.
Подсистема ядра Jmix предоставляет JpaDataStore
, которое хранит сущности JPA в реляционной базе данных. Это основной механизм персистентности в приложениях Jmix. Когда в этом руководстве упоминается хранилище данных, всегда имеется в виду JpaDataStore
, если явно не указано иное.
Дополнение REST DataStore предоставляет RestDataStore
, которое работает с DTO сущностями, сопоставленными с REST API удаленного приложение Jmix. REST хранилище данных имеет некоторые ограничения по сравнению с JPA хранилищем.
Основное хранилище
При создании нового проекта 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
будет загружаться автоматически при обращении к ссылочному атрибуту.