Обновить связанную сущность из обратного вызова прослушивателя событийJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Обновить связанную сущность из обратного вызова прослушивателя событий

Сообщение Anonymous »

Общая проблема
У нас есть сущности, Родитель и Дочерний элемент, с отношениями один-ко-многим между ними. При обновлении родителя мы хотим автоматически обновлять некоторые записи во всех связанных дочерних элементах.

Для простоты мы также сохраняем измененное свойство (значение) в дочернем объекте.

Основная проблема заключается в изменении различных свойств и расчете нового свойства. у родственных детей на основе этих изменений.

Getter/Setter ToString... опущены для простоты.

@Entity общественный класс ParentEntity { @Идентификатор @GeneratedValue частный идентификатор UUID; частное имя строки; частное строковое значение; @OneToMany(mappedBy = "родительский", cascade = CascadeType.ALL) частный List дети; } @Сущность общественный класс ChildEntity { @Идентификатор @GeneratedValue частный идентификатор UUID; @ManyToOne @JoinColumn(name="parent_id") частный родитель ParentEntity; частное строковое значение; } Используемый подход — прослушиватель событий Поскольку изменения вносятся с помощью разных сервисов и методов, мы ищем централизованное решение, поэтому мы решили использовать Event-Listeners в родителе, который запускает процесс обновления во всех его дочерних элементах.

Показаны только дополнительные методы

публичный класс ParentEntity { @PrePersist @PreUpdate недействительный onUpdate() { если (дети != ноль) { this.children.forEach(ChildEntity::update) } } } общественный класс ChildEntity { недействительное обновление () { если (родительский != ноль) { this.value = родительское.getValue(); } } } Проблема Этот подход не всегда обновляет дочерний объект при изменении значения родительского объекта.

Мы выявили множество факторов, влияющих на результат
[*]Аннотация @OneToMany для ParentEntity#children с нетерпеливым/ленивым извлечением [*]Аннотация @Fetch для ParentEntity#children, специфичная для Hibernate, с JOIN/SELECT/SUBSELECT [*]Доступ к дочернему списку в рамках той же транзакции, что и обновление. [*]Специально для весны: используйте findById репозитория или собственный findByName
Мы также пробовали использовать аннотации @EntityGraph, но отказались от этого подхода. поскольку это будет зависеть от доступа, что сводит на нет подход «одного метода».

вызов метода сохранения хранилища внутри транзакции не имеет никакого эффекта.

Это приводит к следующей матрице успеха/неуспеха

Результаты успешные: + неудачные: -

Дочерний список, помеченный режимом @OneToMan fetch LAZY и @Fetch
без аннотаций ПРИСОЕДИНИТЬ ВЫБРАТЬ или ПОДВЫБОР найти по идентификатору - + - найти по идентификатору и доступу + + + без аннотаций ПРИСОЕДИНИТЬ ВЫБРАТЬ или ПОДВЫБОР найти по имени - + - найти по имени и доступу + + +
Дочерний список, аннотированный с помощью @OneToMan fetch EAGER и режима @Fetch
без аннотаций ПРИСОЕДИНИТЬ ВЫБРАТЬ или ПОДВЫБОР найти по идентификатору - - - найти по идентификатору и доступу - - + без аннотаций ПРИСОЕДИНИТЬ ВЫБРАТЬ или ПОДВЫБОР найти по имени + + - найти по имени и доступу + + +
Небольшое примечание: я не мог опубликовать поиск по идентификатору и поиск по имени как одну таблицу — stackoverflow не позволил бы это сделать
Открытые вопросы [*]Почему вызовы репозитория по findById и findByName дают разные результаты? [*]Какую комбинацию аннотаций использовать? [*]Есть ли совершенно другой подход?
Исходный код и некоторые SpringBootTests с дополнительным выводом журнала можно найти на GitHub
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»