数据存储
主数据存储
当使用 Studio 创建一个新的 Jmix 项目时,会带有有一个名为 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 声明:
@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
和其他相关的 bean:
@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
数据存储连接的数据库中。
自定义数据存储
自定义数据存储支持以处理 JPA 实体相同的方式处理某些 DTO 实体 - 通过使用 DataManager
。如果你的 DTO 实体与自定义数据存储关联,则 DataManager
会代理定制数据存储的 CRUD 操作,并能处理其他实体对 DTO 的引用。
我们来看一下创建自定义数据存储的过程。假设一个 transient 的 Metric
实体,存储在内存中。
-
创建一个实现
DataStore
接口的类。该类必须是 Spring prototype bean。下面是一个能够在内存中存储不同类型实体的基本实现。@Component @Scope(BeanDefinition.SCOPE_PROTOTYPE) public class InMemoryStore implements DataStore { // ... }
-
创建一个实现
StoreDescriptor
接口的类。必须是一个 Spring singleton bean,其getBeanName()
方法必须返回上一步创建的实现DataStore
bean 的名称:@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
-
在
jmix.core.store-descriptor-<store_name>
属性中设置StoreDescriptor
bean 名称: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
实例。