Общая проблема
У нас есть сущности, Родитель и Дочерний элемент, с отношениями один-ко-многим между ними. При обновлении родителя мы хотим автоматически обновлять некоторые записи во всех связанных дочерних элементах.
Для простоты мы также сохраняем измененное свойство (значение) в дочернем объекте.
Основная проблема заключается в изменении различных свойств и расчете нового свойства. у родственных детей на основе этих изменений.
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
Обновить связанную сущность из обратного вызова прослушивателя событий ⇐ JAVA
Программисты JAVA общаются здесь
1701271555
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 [b]LAZY[/b] и @Fetch
без аннотаций ПРИСОЕДИНИТЬ ВЫБРАТЬ или ПОДВЫБОР найти по идентификатору - + - найти по идентификатору и доступу + + + без аннотаций ПРИСОЕДИНИТЬ ВЫБРАТЬ или ПОДВЫБОР найти по имени - + - найти по имени и доступу + + +
Дочерний список, аннотированный с помощью @OneToMan fetch [b]EAGER[/b] и режима @Fetch
без аннотаций ПРИСОЕДИНИТЬ ВЫБРАТЬ или ПОДВЫБОР найти по идентификатору - - - найти по идентификатору и доступу - - + без аннотаций ПРИСОЕДИНИТЬ ВЫБРАТЬ или ПОДВЫБОР найти по имени + + - найти по имени и доступу + + +
Небольшое примечание: я не мог опубликовать поиск по идентификатору и поиск по имени как одну таблицу — stackoverflow не позволил бы это сделать
Открытые вопросы [*]Почему вызовы репозитория по findById и findByName дают разные результаты? [*]Какую комбинацию аннотаций использовать? [*]Есть ли совершенно другой подход?
Исходный код и некоторые SpringBootTests с дополнительным выводом журнала можно найти на GitHub
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия