【问题标题】:Spring Data JPA save child object with the ID of parent objectSpring Data JPA用父对象的ID保存子对象
【发布时间】:2021-05-31 08:17:24
【问题描述】:

我有两个对象,一个父母和一个孩子如下:

@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 持久化到数据库中?

【问题讨论】:

  • 请分享您在数据库中保存类别和属性的代码。
  • 我没有编写任何代码来将实体保存到数据库中。我正在使用这样定义的 CrudRepository: public interface CategoryRepository extends JpaRepository 。我用这个接口的save方法。
  • 你能展示你在服务中编写的代码吗?可能问题出在交易中。

标签: spring database spring-data-jpa persistence h2


【解决方案1】:

首先,这个问题不是“Spring Data JPA”问题,而是JPA(可能是Hibernate)问题。


分析

由于您省略了控制器和 JSON 映射的代码,我不得不猜测一下:

  • 事实 1:categoryattributes 之间的关系由属性 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;
}

【讨论】:

  • 我是通过将属性模型设置为所需类别手动完成的,我认为您提出的建议是相同的。
  • @cuneytyvz:“我是通过将属性模型设置为所需的类别来手动完成的”,您是在提出问题之前还是在我回答之后这样做的,并且它是否解决了问题? -- 如果没有,请贴出控制器和dao代码
  • 我做了这个,后来看到你的回复。我添加了一个答案。
【解决方案2】:

我通过手动设置子对象对父对象的引用解决了这个问题:

public Long createCategory(CategoryDto categoryDto) {
    CategoryModel categoryModel = categoryDto.toModel(true,true);
    categoryModel.getAttributes().forEach(a -> a.setCategory(categoryModel));
    return categoryRepository.save(categoryModel).getId();
}

【讨论】:

    猜你喜欢
    • 2020-01-26
    • 1970-01-01
    • 1970-01-01
    • 2021-11-15
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 2019-08-21
    • 2020-08-19
    相关资源
    最近更新 更多