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
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 store
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
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
cuba.persistenceConfig_db1 properties should also be specified in the property files of all used application blocks (
- 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
Orderentity in the main data store and
Customerentity in an additional data store, and you want to have a reference from
Customer. Then do the following:
Orderentity, define an attribute with the type of the
Customeridentifier. The attribute should be annotated with
@SystemLevelto exclude it from various lists available to users, like attributes in Filter:
@SystemLevel @Column(name = "CUSTOMER_ID") private Long customerId;
Orderentity, define a non-persistent reference to
Customerand specify the
customerIdattribute as "related":
@Transient @MetaProperty(related = "customerId") private Customer customer;
customerattribute to appropriate views.
After that, when you load
Orderwith a view including
DataManagerautomatically loads related
Customerfrom 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
DataManagersaves the instances via corresponding
DataStoreimplementations, and then saves the identifier of the customer in the order’s
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.