MyTetra Share
Делитесь знаниями!
Документация DataManager
Время создания: 02.10.2019 08:57
Раздел: INFO - Development - CUBA
Запись: wwwlir/Tetra/master/base/1569977827geilwrda91/text.html на raw.githubusercontent.com

Интерфейс DataManager является универсальным средством для загрузки графов сущностей из базы данных, и для сохранения изменений, произведенных в detached экземплярах сущностей.


В разделе DataManager vs. EntityManager приведена информация о различиях между DataManager и EntityManager .

DataManager на самом деле делегирует выполнение реализациям DataStore , и поддерживает ссылки между сущностями из разных хранилищ. Большинство деталей реализации, описанных ниже, актуальны только когда производится работа через RdbmsStore с сущностями, хранящимися в реляционной БД. Для другого типа хранилища все, кроме сигнатур методов, может отличаться. Для простоты изложения, далее, когда мы говорим просто DataManager, мы будем иметь в виду DataManager через RdbmsStore.

Методы DataManager:

  • load(Class) - загружает сущности указанного типа. Данный метод является точкой входа в fluent API:
  • @Inject
    private DataManager dataManager;

    private Book loadBookById(UUID bookId) {
        return dataManager.load(Book.class).id(bookId).view("book.edit").one();
    }

    private List<BookPublication> loadBookPublications(UUID bookId) {
        return dataManager.load(BookPublication.class)
            .query("select p from library$BookPublication p where p.book.id = :bookId")
            .parameter("bookId", bookId)
            .view("bookPublication.full")
            .list();
    } 
  • loadValues(String query) - загружает пары ключ-значение по запросу, возвращающему скалярные значения. Данный метод является точкой входа в fluent API:
  • List<KeyValueEntity> list = dataManager.loadValues(
            "select o.customer, sum(o.amount) from demo$Order o " +
            "where o.date >= :date group by o.customer")
        .properties("customer", "sum")
        .parameter("date", orderDate)
        .list(); 
  • loadValue(String query, Class valueType) - загружает единственное значение по запросу. Данный метод является точкой входа в fluent API:
  • BigDecimal sum = dataManager.loadValue(
            "select sum(o.amount) from demo$Order o " +
            "where o.date >= :date group by o.customer", BigDecimal.class)
        .parameter("date", orderDate)
        .one(); 
  • load(LoadContext), loadList(LoadContext) - загружает сущности в соответствии с параметрами переданного объекта LoadContext. В LoadContext обязательно должен быть передан либо JPQL-запрос, либо идентификатор сущности. Если передано и то и другое, используется запрос, а идентификатор игнорируется. Примеры:
  • @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(ValueLoadContext) - загружает список пар ключ-значение. Метод принимает объект ValueLoadContext, в котором задается запрос и список ключей. Возвращаемый список содержит экземпляры KeyValueEntity. Например:
  • 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(LoadContext) - возвращает количество записей для запроса, переданного в метод. Когда возможно, для максимальной производительности, стандартная реализация в классе RdbmsStore выполняет запрос select count() с условиями исходного запроса.
  • commit(CommitContext) - сохраняет в базе данных набор сущностей, переданный в объекте CommitContext. Отдельно указываются коллекции сущностей, которые нужно сохранить и которые нужно удалить.
  • Метод возвращает набор экземпляров сущностей, возвращенных из метода EntityManager .merge(), то есть по сути свежие экземпляры, только что обновленные в БД. Дальнейшая работа должна производиться именно с этими возвращенными экземплярами, чтобы предотвратить потерю данных или исключения оптимистичной блокировки. Для того, чтобы обеспечить наличие нужных атрибутов у возвращенных сущностей, с помощью мэп CommitContext.getViews() можно указать представление для каждого сохраняемого экземпляра.

    Примеры сохранения коллекций сущностей:

    @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(Entity, View) - удобный метод для перезагрузки экземпляра сущности с требуемым представлением . Делегирует выполнение методу load().
  • remove(Entity) - удаляет экземпляр сущности из базы данных. Делегирует выполнение методу commit().
  • create(Class) - создает экземпляр данной сущности в памяти. Этот метод просто делегирует в Metadata.create().
  • getReference(Class, Object) - возвращает экземпляр сущности, который может быть использован в качестве ссылки на объект, существующий в базе данных.

Например, если вы создаете экземпляр сущности User, вам необходимо установить ссылку на Group, в которую данный пользователь будет входить. Если вам известен id группы, то вы могли бы загрузить данную группу из БД. Данный метод позволяет получить экземпляр Group без ненужного обращения к БД:

user.setGroup(dataManager.getReference(Group.class, groupId));
dataManager.commit(user); 

Ссылка может также быть использована для удаления существующего объекта по идентификатору:

dataManager.remove(dataManager.getReference(Customer.class, customerId)); 

Запросы

Правила создания запросов аналогичны описанным в разделе Выполнение JPQL-запросов . Отличием является то, что в запросе, выполняемом через DataManager, могут быть использованы только именованные параметры, позиционные не поддерживаются.

Транзакции

DataManager всегда стартует новую транзакцию и по завершении работы выполняет коммит, таким образом возвращая сущности в detached состоянии .

Частичные сущности

Частичная сущность - это экземпляр сущности, в котором может быть загружена только часть локальных атрибутов. По умолчанию, DataManager загружает частичные сущности в соответствии с указанными представлениями . (на самом деле, RdbmsStore просто устанавливает свойство loadPartialEntities у представления в true и передает его дальше в EntityManager ).

В некоторых случаях DataManager загружает все локальные атрибуты и представление определяет только загрузку связей:

  • Загружаемая сущность кэшируется .
  • Для сущности заданы in-memory "read" ограничения .
  • Для сущности задан динамический контроль доступа к атрибутам .
  • Атрибут loadPartialEntities объекта LoadContext установлен в false.


 
MyTetra Share v.0.59
Яндекс индекс цитирования