Я использую 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)
Я не думаю, что вы поняли, что делает CascadeType
.
persist()
, merge()
, refresh()
и remove()
, и оно определенно всегда рекурсивно.Я не могу точно определить точный источник вашей путаницы/проблемы, потому что вы не показали нам никакого кода.
Это ничего не значит для меня. Что значит «создать»? В JPA или Hibernate нет операции под названием «создать». Да ладно мужик. Код или этого не произошло.
Создать означает, когда я выполняю save() в объекте продукта.
Я вижу, вы добавили немного кода, но это все еще не тот код, который мне нужно видеть. (Код, который вызывает Session
.)
Ассоциации в модели предметной области представляют, как разные сущности предметной области связаны друг с другом. часто эти отношения могут быть выражены как отношения родитель-потомок.
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, чего раньше не было.
Когда я создаю «Продукт», создается TextContent, но переводы создаются без отношения, список переводов textcontent пуст.