5.2.6.10. DataManager

DataManager interface provides CRUD functionality on both middle and client tiers. It is a universal tool for loading entity graphs from the database and saving changed detached entity instances.

Tip

See DataManager vs. EntityManager for information on differences between DataManager and EntityManager.

DataManager in fact just delegates to a DataStore implementation and handles cross-database references if needed. The most implementation details described below are in effect when you work with entities stored in a relational database through the standard RdbmsStore. For another type of data store, everything except the interface method signatures can be different. For simplicity, when we write "DataManager" without additional clarification, we mean "DataManager via RdbmsStore".

DataManager methods are listed below:

  • load(), loadList() – loads a graph of entities according to the parameters of the LoadContext object passed to it.

    LoadContext must include either a JPQL query or an entity identifier. If both are defined, the query is used, and the identifier is ignored. The rules for queries creation are similar to those described in Executing JPQL Queries . The difference is that the query in LoadContext may only use named parameters; positional parameters are not supported.

    Examples of loading entities in the screen controller:

    @Inject
    private DataManager dataManager;
    
    private Book loadBookById(UUID bookId) {
        LoadContext<Book> loadContext = LoadContext.create(Book.class)
                .setId(bookId).setView("book.edit");
        return dataManager.load(loadContext);
    }
    
    private List<BookPublication> loadBookPublications(UUID bookId) {
        LoadContext<BookPublication> loadContext = LoadContext.create(BookPublication.class)
                .setQuery(LoadContext.createQuery("select p from library$BookPublication p where p.book.id = :bookId")
                    .setParameter("bookId", bookId))
                .setView("bookPublication.full");
        return dataManager.loadList(loadContext);
    }
  • loadValues() - loads a list of key-value pairs. The method accepts ValueLoadContext which defines a query for scalar values and a list of keys. The returned list contains instances of KeyValueEntity. For example:

    ValueLoadContext context = ValueLoadContext.create()
            .setQuery(ValueLoadContext.createQuery(
                        "select o.customer, sum(o.amount) from demo$Order o " +
                        "where o.date >= :date group by o.customer")
                .setParameter("date", orderDate))
            .addProperty("customer")
            .addProperty("sum");
    List<KeyValueEntity> list = dataManager.loadValues(context);
  • getCount() - returns a number of records for a query passed to the method. When possible, the standard implementation in RdbmsStore executes select count() query with the same conditions as in the original query for maximum performance.

  • commit() – saves a set of entities passed in CommitContext to the database. Collections of entities for updating and deletion must be specified separately.

    The method returns the set of entity instances returned by EntityManager.merge(); essentially these are fresh instances just updated in DB. Further work should be performed with these returned instances to prevent data loss or optimistic locking. You can ensure that required attributes are present in the returned entities by setting a view for each saved instance using CommitContext.getViews() map.

    Examples for saving a collection of entities:

    @Inject
    private DataManager dataManager;
    
    private void saveBookInstances(List<BookInstance> toSave, List<BookInstance> toDelete) {
        CommitContext commitContext = new CommitContext(toSave, toDelete);
        dataManager.commit(commitContext);
    }
    
    private Set<Entity> saveAndReturnBookInstances(List<BookInstance> toSave, View view) {
        CommitContext commitContext = new CommitContext();
        for (BookInstance bookInstance : toSave) {
            commitContext.addInstanceToCommit(bookInstance, view);
        }
        return dataManager.commit(commitContext);
    }
  • reload() - convenience methods to reload a specified instance from the database with the required view. They delegate to load() method.

  • remove() - removes a specified instance from the database. Delegates to commit() method.

Transactions

DataManager always starts a new transaction and commits it on operation completion, thus returning entities in the detached state.

Partial entities

By default, DataManager loads partial entities according to views. It will load all local attributes and use views only for fetching references in the following cases:

  • The loaded entity is cached.

  • In-memory "read" constraints are defined for an entity.

  • The loadPartialEntities attribute of LoadContext is set to false.