我在Java应用程序中使用Hibernate,我注意到cascadtype属性似乎只适用于对象的直接子对象,而不适用于子对象的子对象。
例如,假设我有一个Product具有TextContent对象作为其字段之一。如果我将Customer字段中的cascadtype属性设置为ALL,则对Product所做的任何更改对象将自动持久化,当TextContent对象被持久化。但是TextContent有一个列表翻译对象作为它的一个字段,并且我将翻译字段的cascadtype属性设置为ALL,对TextContent所做的更改对象将不会自动持久化,当翻译对象被持久化(翻译中的FK是NULL而不是TextContent的id)。
为什么会这样?是否有一种方法,使cascadtype属性工作的孩子的孩子,以及?
实体:
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)
域模型中的关联表示不同的域实体如何相互关联。通常这些关系可以表示为亲子关系。
Cascade作用于父表和子表中使用f.k key直接相关的记录。
因为Hibernate JPA将引用完整性问题委托给底层SQL数据库的外键约束。
这个设计决策有一个很好的理由。因为可以在关联级别控制分离对象的合并。
所以只有那些与你的父实体关联的子实体得到级联,而不是子实体的子实体。
我认为你不了解CascadeType
是做什么的。
- 不是关于与数据库同步更改(更新)。[默认情况下]对实体的更改会在刷新时自动检测并同步到数据库,只要在刷新持久性上下文时该实体与持久性上下文相关联。
- 级联就是对
persist()
、merge()
、refresh()
、remove()
等显式操作进行级联,绝对是递归的。
我不能确切地指出你的困惑/问题的根源,因为你没有给我们看任何代码。
由于某些原因,hibernate需要引用TextContent对象在翻译对象,即使该引用可以从Translation的子对象推导出来(TextContent) .
我设法通过修改Translations的setter来解决它。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相关联,