【问题标题】:Foreign-key in tb_child is null with bidirectional one-to-many relationshiptb_child 中的外键为空,具有双向一对多关系
【发布时间】:2022-02-05 11:49:50
【问题描述】:

我正在使用 Java Persistence API 创建我的第一个 Spring Boot 应用程序,以写入和读取 postgres 数据库。我查看了许多教程和帖子以找出我的确切问题,似乎我目前与两个实体(ParentChild)具有双向一对多关系,但是当我写入数据库时​​,child 列始终为 null

父实体:

@Entity
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "tb_parent")
public class Parent {
    @Schema(description = "id of the parent")
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Schema(description = "child-list of the application")
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch=FetchType.LAZY, orphanRemoval = true)
    private Set<Child> children;
}

子实体:

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "tb_child")
public class Child{
    @Schema(description = "id of the child")
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @JsonBackReference
    @ManyToOne(targetEntity = Parent.class, fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id", referencedColumnName = "id", updatable = true, insertable = true)
    private Parent parent;
}

父服务:

...
    @Override
    public Parent create(Parent parent) {
        log.info("save new parent: {}", parent);
        return parentRepo.save(parent);   // the repo is an interface that extends the JpaRepository
    }
...

调用create 方法后,我在tb_parent 中有一个parent 行和一个生成的id,在tb_child 中有一个或多个child 行和一个生成的id 和一个parent_id 列的 null 值。

尽管我能找到很多描述类似问题的帖子,但我还没有找到适合我的解决方案。

更新 #1:

一个常见的建议是在所有child 元素中手动设置parent 对象。但是,由于循环结构,这会导致 Stackoverflow 异常。

    public void setChildren(Set<Child> children) {
        children.forEach(child -> child.setParent(this));
        this.children = children;
    }

此外,这有点让人感觉不舒服,因为几乎所有内容都由 JPA Annotations 自动管理,然后您必须手动同步数据。

【问题讨论】:

  • 这能回答你的问题吗? Spring Data Jpa OneToMany save bidirectional
  • @GeorgyLvov 我已经采用类似的方法将父元素存储在所有子元素上,但是,由于循环结构,这会导致 Stackoverflow 异常。请参阅更新 #1。
  • StackoverflowError 是由于您的实体上的@Data 注释,这里有一个有用的link 关于它。

标签: java spring-boot hibernate jpa


【解决方案1】:

感谢 Georgy Lvov,我能够找到最有效的解决方案。我必须执行以下步骤:

  1. 删除 Georgy Lvov 建议的 @Data 注释(非常感谢!)这基本上避免了所有属性的生成 getter 和 setter 方法以及方法 equals()、hashCode() ,以及 Lombok 的 toString() 导致 Stackoverflow 异常。
  2. 使用@JsonManagedReference 注释在Parent 类中注释Set&lt;Child&gt; children; 变量。见下文:
    @JsonManagedReference
    @Schema(description = "child-list of the application")
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch=FetchType.LAZY, orphanRemoval = true)
    private Set<Child> children;
  1. 使用@JsonBackReference 注释在Child 类中注释private Parent parent;。见下文:
    @JsonBackReference
    @ManyToOne(targetEntity = Parent.class, fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id", referencedColumnName = "id", updatable = true, insertable = true)
    private Parent parent;

@JsonBackReference 在创建openapi.json 文件时似乎也避免了循环结构。

【讨论】:

  • 仍然有循环:/
猜你喜欢
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多