Почему свойство CascadeType Hibernate работает только для дочерних элементов объекта, а не для дочерних элементов?

Я использую Hibernate для своего Java-приложения и заметил, что свойство CascadeType работает только для непосредственных дочерних элементов объекта, но не для дочерних элементов дочерних элементов.

Например, предположим, что у меня есть объект Product, одним из полей которого является объект TextContent. Если я задаю для свойства CascadeType значение ALL в поле Customer, любые изменения, внесенные в объект Product, будут автоматически сохраняться при сохранении объекта TextContent.

Однако TextContent имеет список объектов перевода в качестве одного из своих полей, и я установил для свойства CascadeType значение ALL в поле переводов, изменения, внесенные в объект TextContent, не будут автоматически сохраняться при сохранении объекта перевода (FK в Перевод равен NULL вместо идентификатора TextContent).

Почему это так? Есть ли способ заставить свойство CascadeType работать и для детей детей?

Объекты:

public class Product {
  private Integer id;

  @ManyToOne(cascade = CascadeType.ALL)
  public TextContent textContentName;
}

public class TextContent {
  private Integer id;

  @OneToMany(mappedBy = "textContent", cascade = CascadeType.ALL)
  private List<Translation> translations;
}

public class Translation {
  private Integer id;

  private String translation;

  @ManyToOne()
  private Language language;

  @JsonIgnore()
  @ManyToOne()
  private TextContent textContent;
}

public class Language {
  private Integer id;
    
  private String acronym;
}

JSON продукта, отправленного на контроллер:

{
  "id": null,
  "textContentName": {
    "id": null,
    "translations": [
      {
        "id": null,
        "translation": "Product name in English",
        "language":{
          "id": 1,
          "acronym": "en"
        }
      },
      {
        "id": null,
        "translation": "Nombre del producto en Español",
        "language":{
          "id": 2,
          "acronym": "es"
        }
      }
    ]
  }
}

JPA Исполнение контроллера:

productRepository.save(product)
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
0
0
72
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я не думаю, что вы поняли, что делает CascadeType.

  1. Речь не идет о синхронизации изменений (обновлений) с базой данных. [По умолчанию] изменение объекта автоматически обнаруживается и синхронизируется с базой данных во время сброса, если объект связан с контекстом сохраняемости при сбросе контекста сохраняемости.
  2. Каскадирование — это каскадирование явных операций, таких как persist(), merge(), refresh() и remove(), и оно определенно всегда рекурсивно.

Я не могу точно определить точный источник вашей путаницы/проблемы, потому что вы не показали нам никакого кода.

Когда я создаю «Продукт», создается TextContent, но переводы создаются без отношения, список переводов textcontent пуст.

JuamBer 12.04.2023 12:04

Это ничего не значит для меня. Что значит «создать»? В JPA или Hibernate нет операции под названием «создать». Да ладно мужик. Код или этого не произошло.

Gavin King 12.04.2023 12:16

Создать означает, когда я выполняю save() в объекте продукта.

JuamBer 12.04.2023 12:21

Я вижу, вы добавили немного кода, но это все еще не тот код, который мне нужно видеть. (Код, который вызывает Session.)

Gavin King 12.04.2023 13:37

Ассоциации в модели предметной области представляют, как разные сущности предметной области связаны друг с другом. часто эти отношения могут быть выражены как отношения родитель-потомок.

Cascade работает с записями из родительских и дочерних таблиц, которые напрямую связаны с помощью F.key.

Поскольку Hibernate JPA делегирует вопросы ссылочной целостности ограничениям внешнего ключа базовой базы данных SQL.

Для такого дизайнерского решения есть веская причина. потому что может, например, управлять слиянием отдельного объекта на уровне ассоциации.

Таким образом, только те дочерние элементы, которые находятся в ассоциации вашего родительского объекта, получают каскад, а не дочерний элемент дочернего элемента.

Ответ принят как подходящий

По какой-то причине hibernate нуждается в ссылке объекта TextContent в объекте перевода, даже если эта ссылка выводится из дочернего элемента перевода (TextContent).

Мне удалось решить эту проблему, изменив установщик списка переводов объекта TextContent, переходящего из:

public class TextContent {
  private Integer id;

  @OneToMany(mappedBy = "textContent", cascade = CascadeType.ALL)
  private List<Translation> translations;

  public setTranslations(List<Translation> translations){
      this.translations = translations;
  }
}

к:

public class TextContent {
  private Integer id;

  @OneToMany(mappedBy = "textContent", cascade = CascadeType.ALL)
  private List<Translation> translations;

  public setTranslations(List<Translation> translations){
      translations.forEach((translation) => {
          translation.setTextContent(this);
      });
      this.translations = translations;
  }
}

Выполнение этого при вызове метода save() продукта создает как объект TextContent, так и переводы, связанные с одним и тем же TextContent, чего раньше не было.

Другие вопросы по теме