Spring 数据 JPA 保存 child object ID 为 parent object
Spring Data JPA save child object with the ID of parent object
我有两个 object,一个 parent 和一个 child 如下:
@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 objects 但我省略了它们。
当我尝试使用此有效负载保存类别 object 时,属性值也在属性 table 中创建,但具有 null 类别 ID。
{
"name":"Chemicals",
"attributes":[
{"name": "volume"}, {"name":"humidity"}
]
}
我该怎么做才能将我的属性值与之前创建的类别 ID 一起保存到数据库中?
首先,这个问题不是“Spring Data JPA”的问题,而是JPA(可能是Hibernate)的问题。
分析
由于您遗漏了控制器和 JSON 映射的代码,我不得不猜测一下:
- 事实1:类别和属性之间的关系由属性
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();
}
我有两个 object,一个 parent 和一个 child 如下:
@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 objects 但我省略了它们。 当我尝试使用此有效负载保存类别 object 时,属性值也在属性 table 中创建,但具有 null 类别 ID。
{
"name":"Chemicals",
"attributes":[
{"name": "volume"}, {"name":"humidity"}
]
}
我该怎么做才能将我的属性值与之前创建的类别 ID 一起保存到数据库中?
首先,这个问题不是“Spring Data JPA”的问题,而是JPA(可能是Hibernate)的问题。
分析
由于您遗漏了控制器和 JSON 映射的代码,我不得不猜测一下:
- 事实1:类别和属性之间的关系由属性
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();
}