EntityChangedEvent
- это ApplicationEvent
, который посылается фреймворком на среднем слое, когда некоторый экземпляр сущности сохраняется в базу данных. Данное событие может быть обработано как внутри текущей транзакции, так и после ее завершения (при использовании @TransactionalEventListener).
Tip
|
Событие посылается только если на сущности есть аннотация |
Объект EntityChangedEvent
содержит не сам измененный экземпляр сущности, а только его id. Кроме того, метод getOldValue(attributeName)
возвращает идентификаторы ссылок вместо самих объектов. Поэтому при необходимости, разработчик должен загрузить требуемые сущности с указанием требуемого представления и других параметров.
Ниже приведен пример обработки EntityChangedEvent
для сущности Customer
в текущей транзакции и после ее завершения:
link:../../../../source/middleware/entityChangedEvent_usage_1.java[role=include]
-
- данный обработчик вызывается внутри текущей транзакции.
-
- id измененной сущности.
-
- тип изменения:
CREATED
,UPDATED
orDELETED
. -
- можно проверить, изменился ли определенный атрибут.
-
- можно получить старое значение измененного атрибута.
-
- данный обработчик вызывается после коммита транзакции.
-
- после коммита событие содержит те же значения что и внутри транзакции.
Если обработчик вызывается внутри транзакции, ее можно откатить путем выбрасывания исключения. При этом в БД никакие изменения не сохранятся. Если вы не хотите, чтобы пользователь получил какое-либо оповещение, используйте SilentException
.
Если "after commit" обработчик выбрасывает исключение, оно будет залоггировано, но не передано клиенту (т.е. пользователь не получит сообщения об ошибке в UI).
Warning
|
При обработке В обработчике, вызываемом после коммита транзакции ( |
Ниже приведен пример использования EntityChangedEvent
для изменения связанных сущностей.
Предположим, имеются сущности Order
, OrderLine
и Product
, как в примере Quick Start Sales Application, но сущность Product
дополнительно имеет булевский атрибут special
, а у сущности Order
есть атрибут numberOfSpecialProducts
, который должен быть пересчитан при создании и удалении экземпляров OrderLine
в составе Order
.
Создадим следующий класс с методом, аннотированным @EventListener
, который будет вызываться при изменении сущностей OrderLine
перед коммитом транзакции:
link:../../../../source/middleware/entityChangedEvent_usage_2.java[role=include]
-
- если экземпляр
OrderLine
не удален, можно загрузить его из БД по идентификатору. -
- метод
event.getEntityId()
возвращает id измененного экземпляраOrderLine
. -
- используем представление, которое содержит
OrderLine
вместе сOrder
, которому он принадлежит. Представление должно содержать атрибутOrder.numberOfSpecialProducts
, так как его необходимо будет обновить. -
- получаем
Order
из загруженногоOrderLine
. -
- если экземпляр
OrderLine
был только что удален, его нельзя загрузить из БД, но методevent.getChanges()
возвращает все атрибуты удаленной сущности, включая идентификаторы связанных сущностей. Поэтому можно загрузить связанныйOrder
по его id. -
- загружаем все экземпляры
OrderLine
для данногоOrder
, отфильтровываем поProduct.special
и считаем их. Представление должно содержатьOrderLine
вместе со связаннымProduct
. -
- сохраняем
Order
после изменения его атрибута.