3.4.2. Data Stores
A usual way of working with data in CUBA applications is manipulating entities - either declaratively through data-aware visual components, or programmatically via DataManager or EntityManager. The entities are mapped to data in a data store, which is usually a relational database. An application can connect to multiple data stores so its data model will contain entities mapped to data located in different databases.
An entity can belong only to a single data store. You can display entities from different data stores on a single UI screen, and DataManager
will ensure they will be dispatched to appropriate data stores on save. Depending on the entity type, DataManager
selects a registered data store represented by an implementation of the DataStore
interface and delegates loading and saving entities to it. When you control transactions in your code and work with entities via EntityManager
, you have to specify explicitly what data store to use. See the Persistence interface methods and @Transactional annotation parameters for details.
The platform contains a single implementation of the DataStore
interface called RdbmsStore
. It is designed to work with relational databases through the ORM layer. You can implement DataStore
in your project to provide integration, for example, with a non-relational database or an external system having REST interface.
In any CUBA application, there is always the main data store which contains system and security entities and where the users log in. When we mention a database in this manual, we always mean the main data store if not explicitly stated otherwise. The main data store must be a relational database connected through a JDBC data source. An additional data store can be any implementation of the DataStore
interface.
CUBA Studio allows you to set up additional data stores, see the documentation. It automatically creates all required application properties and JDBC data sources, as well as maintains additional |
The information below can help you in troubleshooting or if you don’t use Studio.
Additional data store names are specified in the cuba.additionalStores application property. If the additional store is RdbmsStore
, the following properties should be defined for it:
-
cuba.dbmsType_<store_name>
- type of the data store DBMS. -
cuba.persistenceConfig_<store_name>
- location of the data storepersistence.xml
file. -
cuba.dataSource…
- connection parameters as described in Connecting to Databases.
If you implement the DataStore
interface in your project, the name of the implementation bean must be specified in the cuba.storeImpl_<store_name>
application property.
For example, if you work with two additional data stores: db1
(a PostgreSQL database) and mem1
(a custom in-memory storage implemented by some project bean), the following application properties must be specified in the app.properties
file of your core
module:
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
The cuba.additionalStores
and cuba.persistenceConfig_db1
properties should also be specified in the property files of all used application blocks (web-app.properties
, portal-app.properties
, etc.).
- References between entities from different data stores
-
DataManager can automatically maintain TO-ONE references between entities from different data stores, if they are properly defined. For example, consider the case when you have
Order
entity in the main data store andCustomer
entity in an additional data store, and you want to have a reference fromOrder
toCustomer
. Then do the following:-
In the
Order
entity, define an attribute with the type of theCustomer
identifier. The attribute should be annotated with@SystemLevel
to exclude it from various lists available to users, like attributes in Filter:@SystemLevel @Column(name = "CUSTOMER_ID") private Long customerId;
-
In the
Order
entity, define a non-persistent reference toCustomer
and specify thecustomerId
attribute as "related":@Transient @MetaProperty(related = "customerId") private Customer customer;
-
Include non-persistent
customer
attribute to appropriate views.
After that, when you load
Order
with a view includingcustomer
attribute,DataManager
automatically loads relatedCustomer
from the additional data store. The loading of collections is optimized for performance: after loading a list of orders, the loading of references from the additional data store is done in batches. The size of the batch is defined by the cuba.crossDataStoreReferenceLoadingBatchSize application property.When you commit an entity graph which includes
Order
withCustomer
,DataManager
saves the instances via correspondingDataStore
implementations, and then saves the identifier of the customer in the order’scustomerId
attribute.Cross-datastore references are also supported by the Filter component.
CUBA Studio automatically maintains the set of attributes for cross-datastore references when you select an entity from a different data store as an association.
-