8. Использование событий сущности
На этом этапе вы завершили разработку модели данных и пользовательского интерфейса приложения. Но в логике приложения есть недостаток: сотрудники могут видеть и выполнять свои шаги по онбордингу на экране My onboarding
, но атрибут Onboarding status
сущности User
не обновляется соответствующим образом.
В этой главе вы реализуете недостающую часть: атрибут Onboarding status
сущности User
будет обновляться всякий раз, когда изменяется состояние соответствующих экземпляров UserStep
.
Создание слушателя EntityChangedEvent
Если ваше приложение запущено, остановите его с помощью кнопки Stop () на главной панели инструментов.
В окне инструментов Jmix нажмите New () → Event Listener:
На первом шаге мастера Subscribe to Event выберите Entity Event:
Нажмите кнопку Next.
На следующем шаге мастера выберите UserStep
в поле Entity и установите флажок Entity Changed (before commit):
Нажмите на кнопку Create.
Studio создаст Spring бин с помощью метода, аннотированного @EventListener
:
@Component
public class UserStepEventListener {
@EventListener
public void onUserStepChangedBeforeCommit(EntityChangedEvent<UserStep> event) {
}
}
Фреймворк будет вызывать этот метод каждый раз после сохранения измененного экземпляра UserStep
в базе данных, но перед фиксацией транзакции базы данных. Если метод выдает исключение, произойдет откат транзакции.
Метод принимает объект EntityChangedEvent
, который содержит идентификатор измененной сущности, тип изменения (создание/обновление/удаление) и информацию об измененных атрибутах.
Реализуйте слушатель, как показано ниже:
package com.company.onboarding.listener;
import com.company.onboarding.entity.OnboardingStatus;
import com.company.onboarding.entity.User;
import com.company.onboarding.entity.UserStep;
import io.jmix.core.DataManager;
import io.jmix.core.Id;
import io.jmix.core.event.EntityChangedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class UserStepEventListener {
@Autowired
private DataManager dataManager;
@EventListener
public void onUserStepChangedBeforeCommit(EntityChangedEvent<UserStep> event) {
User user;
if (event.getType() != EntityChangedEvent.Type.DELETED) {
Id<UserStep> userStepId = event.getEntityId(); (1)
UserStep userStep = dataManager.load(userStepId).one();
user = userStep.getUser();
} else {
Id<User> userId = event.getChanges().getOldReferenceId("user"); (2)
if (userId == null) {
throw new IllegalStateException("Cannot get User from deleted UserStep");
}
user = dataManager.load(userId).one();
}
long completedCount = user.getSteps().stream()
.filter(us -> us.getCompletedDate() != null)
.count();
if (completedCount == 0) {
user.setOnboardingStatus(OnboardingStatus.NOT_STARTED); (3)
} else if (completedCount == user.getSteps().size()) {
user.setOnboardingStatus(OnboardingStatus.COMPLETED);
} else {
user.setOnboardingStatus(OnboardingStatus.IN_PROGRESS);
}
dataManager.save(user); (4)
}
}
1 | Если экземпляр UserStep был создан или обновлен, получить его идентификатор с помощью метода getEntityId() события. Затем загрузить экземпляр и получить связанный экземпляр User . |
2 | Если UserStep был удален, он больше не может быть загружен из базы данных. Но в этом случае event.getChanges() предоставляет значения всех атрибутов удаленного объекта. |
3 | Установить для атрибута onboardingStatus связанного пользователя значение, зависящее от состояния всех его элементов UserStep . |
4 | Сохранить обновленный экземпляр User в базе данных. |
При наличии этого слушателя согласованность между коллекцией экземпляров UserStep
и атрибутом onboardingStatus
сущности User
будет поддерживаться независимо от того, какой процесс изменяет экземпляры UserStep
. Например, вы можете изменить UserStep
непосредственно через Administration → Entity Inspector и по-прежнему видеть соответствующее изменение User.onboardingStatus
.
Вы можете полагаться на слушателей событий EntityChangedEvent при работе с данными через DataManager . Если вы сохраняете изменения с помощью EntityManager или JDBC, слушатели не вызываются.
|
Резюме
Слушатели EntityChangedEvent могут использоваться для поддержания согласованности данных и выполнения бизнес-логики в текущей транзакции или после ее завершения. Слушатели EntityChangedEvent могут использоваться для поддержания согласованности данных и выполнения бизнес-логики в текущей транзакции или после ее завершения.