Работа с сущностями в UI

Сущности, загруженные в экран, становятся связанными с компонентами экрана, такими как контейнеры данных и DataContext. Эта связь возникает потому, что контейнеры данных и DataContext регистрируют слушателей, которые реагируют на изменения атрибутов сущности. При передаче загруженных сущностей в сервисы для изменения и сохранения, экземпляры сущностей должны быть изолированы от компонентов экрана. В противном случае изменения, внесённые сервисом, будут напрямую влиять на состояние экрана. Кроме того, существует риск утечек памяти, если сущности помещаются сервисом в какой-либо кэш.

Стандартная реализация DataContext обеспечивает правильную изоляцию сохраняемых экземпляров при сохранении сущностей в DataManager. Это достигается за счёт использования бина io.jmix.core.Copier.

Вы можете сделать то же самое для изоляции сущностей при их передаче из экранов в кастомные сервисы. В следующем примере показано, как сохранить сущность через сервис:

@ViewComponent
private DataContext dataContext;
@Autowired
private DepartmentService departmentService;
@Autowired
private Copier copier;

private void saveToCustomService(Department entity) {
    Department entityCopy = copier.copy(entity); (1)

    Department savedEntity = departmentService.saveEntity(entityCopy); (2)

    Department ignored = dataContext.merge(savedEntity);(3)
}
1 Создаём копию сущности, чтобы отделить экземпляр, представляющий состояние экрана, от того, который сохраняется.
2 Отправляем копию в сервис.
3 Если необходимо обновить состояние экрана изменениями, внесёнными в сущность сервисом, поместите возвращённый экземпляр обратно в DataContext. В данном случае результат операции merge() можно безопасно игнорировать.

При использовании saveDelegate для перехвата стандартной процедуры сохранения DataContext, учтите следующие отличия от обычного метода, показанного выше:

  • Объект SaveContext уже содержит копии сущностей, связанных с компонентами экрана, поэтому вам не нужно создавать копии снова.

  • Сохранённые сущности, возвращённые в результирующем Set из обработчика, автоматически помещаются обратно в DataContext, поэтому вам не нужно явно вызывать операцию merge().

См. также онлайн-пример Сохранение сущности кастомным сервисом, который демонстрирует, как изолировать сущности при их отправке с экрана в пользовательский сервис.