3.4.2. 数据存储
在 CUBA 应用程序中处理数据的常用方法是操作实体 - 可通过具有数据感知功能的可视化组件进行声明式处理,也可通过 DataManager 或 EntityManager 进行编程式处理。实体映射到数据存储中的数据,数据存储通常是关系型数据库。应用程序可以连接到多个数据存储,因此其数据模型将包含映射到位于不同数据库中的数据的实体。
实体只能属于单个数据存储,但是可以在单个 UI 界面上显示来自不同数据存储的实体,DataManager
可以确保在保存时将实体分派到适当的数据存储中去。根据实体类型,DataManager
选择一个已注册的数据存储,这个数据存储实现了 DataStore
接口,然后委托其加载和保存实体。当以编程的方式控制事务并通过 EntityManager
使用实体时,必须明确指定要使用的数据存储。有关详细信息,请参阅 Persistence 接口方法和 @Transactional 注解参数。
平台提供了 DataStore
接口的单一实现,名称为 RdbmsStore
,这个实现的目的是通过 ORM 层来使用关系型数据库。可以在自己的项目中实现 DataStore
接口以进行数据整合,例如,可以与非关系型数据库或具有 REST 接口的外部系统进行数据整合。
在任何 CUBA 应用程序中,必定存在一个主数据存储,它包含系统实体和安全实体,用户登录也是在主数据存储。在本手册中提及数据库时,如果没有明确说明,则指的是主数据存储。主数据存储必须是通过 JDBC 数据源连接的关系型数据库。附加数据存储可以是任何 DataStore
接口的实现。
使用 CUBA Studio 可以配置附加数据存储,参考 文档 。会自动创建所有需要的应用程序属性和 JDBC 数据源,并能维护额外添加的 |
如果没有使用 Studio 的话,下面的信息可以帮助你排查问题。
附加数据存储的名称通过 cuba.additionalStores 应用程序属性指定。如果附加存储是 RdbmsStore
,还为其定义了下面这些属性:
-
cuba.dbmsType_<store_name>
- 数据存储 DBMS 类型。 -
cuba.persistenceConfig_<store_name>
- 数据存储对应的persistence.xml
文件位置。 -
cuba.dataSource…
- 连接至数据库描述的连接参数。
如果项目中实现了 DataStore
接口,实现类的名称必须使用 cuba.storeImpl_<store_name>
属性定义。
比如,如果使用了两个附加存储 db1
(PostgreSQL 数据库)和 mem1
(一个自定义的内存存储,通过某些项目中的 bean 实现),core
模块的 app.properties
文件必须定义以下属性:
cuba.additionalStores = db1, mem1
# RdbmsStore for Postgres database with data source obtained from JNDI
cuba.dbmsType_db1 = postgres
cuba.persistenceConfig_db1 = com/company/sample/db1-persistence.xml
cuba.dataSourceJndiName_db1 = jdbc/db1
# Custom store
cuba.storeImpl_mem1 = sample_InMemoryStore
还应在所有应用程序 block 使用的属性文件(web-app.properties
、 portal-app.properties
等)中指定 cuba.additionalStores
和 cuba.persistenceConfig_db1
属性。
- 来自不同数据存储的实体之间的引用
-
如果正确定义了 DataManager,则可以自动维护来自不同数据存储的实体之间的 TO-ONE 引用。比如,在主数据存储中有
Order
实体,在附加数据存储中有Customer
实体,并且希望在Order
中引用Customer
。可以这样做:-
在
Order
实体中,定义一个存储Customer
实体 ID 的属性。该属性应使用@SystemLevel
注解,以将其从用户可用的各种列表中排除,例如 Filter 中的可选属性:@SystemLevel @Column(name = "CUSTOMER_ID") private Long customerId;
-
在
Order
实体中,定义对Customer
的非持久引用,并将 "related" 指定为customerId
:@Transient @MetaProperty(related = "customerId") private Customer customer;
-
在适当的视图中包含非持久化的
customer
属性。
之后,当使用包含
customer
属性的视图加载Order
时,DataManager
会自动从附加数据存储加载关联的Customer
。集合的加载针对性能进行了优化:在加载 Order 列表之后,从附加数据存储加载引用的 Customer 是分批完成的。每批加载的记录数由 cuba.crossDataStoreReferenceLoadingBatchSize 应用程序属性定义。当提交引用了
Customer
的Order
实体图时,DataManager
会通过相应的DataStore
进行数据保存,然后将 Customer 的 ID 保存在 Order 的customerId
属性中。Filter 组件也支持跨数据存储引用。
在 Studio 中,如果使用了跨数据存储的实体引用属性,Studio 会自动维护这种引用关系。
-