问题描述
@Entity
@Table(name="category")
public class CategoryModel {
private @Id @GeneratedValue Long id;
private String name;
@OnetoMany(mappedBy="category",cascade=CascadeType.PERSIST)
private List<AttributeModel> attributes;
}
@Entity
@Table(name="attribute")
public class AttributeModel {
private @Id @GeneratedValue Long id;
private String name;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="category_id")
private CategoryModel category;
}
我也有映射到这些模型对象的 dtos,但我忽略了它们。 当我尝试使用此有效负载保存类别对象时,属性值也在属性表中创建,但具有 null 类别 ID。
{
"name":"Chemicals","attributes":[
{"name": "volume"},{"name":"humidity"}
]
}
如何将我的属性值与在它们之前创建的类别 ID 一起保存到数据库中?
解决方法
首先,这个问题不是“Spring Data JPA”问题,而是JPA(可能是Hibernate)问题。
分析
由于您省略了控制器和 JSON 映射的代码,我不得不猜测一下:
- 事实 1:category 和 attributes 之间的关系由属性
AttributeModel.category
控制,而不是由CategoryModel.attributes
控制。 (这就是 JPA 的工作方式。 -
观察 2:您的 JSON 对象定义了
CategoryModel.attributes
(即与 JPA 的工作方式相反)。
在不知道您的 JSON 映射配置和控制器代码的情况下,我会猜测问题是:您的 JSON 映射器在反序列化 JSON 时没有设置 AttributeModel.category
字段对象。
解决方案
因此您需要在反序列化期间指示 JSON 映射器设置 AttributeModel.category
字段。如果您使用 Jackson,则可以使用:
-
@JsonManagedReference
和 @JsonBackReference
@Entity
@Table(name="category")
public class CategoryModel {
...
@JsonManagedReference
@OneToMany(mappedBy="category",cascade=CascadeType.PERSIST)
private List<AttributeModel> attributes;
}
@Entity
@Table(name="attribute")
public class AttributeModel {
...
@JsonBackReference
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="category_id")
private CategoryModel category;
}
,
我通过手动设置子对象对父对象的引用解决了这个问题:
public Long createCategory(CategoryDto categoryDto) {
CategoryModel categoryModel = categoryDto.toModel(true,true);
categoryModel.getAttributes().forEach(a -> a.setCategory(categoryModel));
return categoryRepository.save(categoryModel).getId();
}