如何使用Spring JPA在一对多关系中的子对象上触发saveAll?

cnwbcb6i  于 8个月前  发布在  Spring
关注(0)|答案(1)|浏览(90)

在后台,我试图通过启用hibernate.jdbc.batch_size属性来加快数据库插入速度。我已经添加了这个属性,但似乎插入仍然没有优化。我研究发现batch_size属性应该与JpaRepository.saveAll方法结合使用。
问题是,当我保存父对象时,它不会触发对子列表的“saveAll”操作。而当我试图分别保存它们时,我在子对象中的外键上得到了一个约束冲突。
我尝试分离对象(删除关系)并单独保存它们。然而,当我这样做时,我得到一个“在批处理发布时,它仍然包含JDBC语句”,后面跟着一个“不能将NULL插入到(child_object.foreign_key)”。
以下是对象的片段以及它们的设置方式:

@Entity
@Table(name="PARENT")
class Parent {

  @Id
  @Column(name="PARENT_ID", length=36)
  private String parentId;
  
  // removed property below to "separate" objects
  // also tried changing @OneToMany to @Transient
  @OneToMany(mappedBy="parent") 
  private List<Child> children;
}

@Entity
@Table(name="CHILD")
class Child {

  @Id
  @GeneratedValue(generator="system-uuid")
  @GenericGenerator(name="system-uuid", strategy="uuid")
  @Column(name="CHILD_ID", length=36)
  private String childId;

  @Column(name="PARENT_ID", insertable=false, updatable=false)
  private String parentId;
  
  // removed property below to "separate" objects
  @ManyToOne
  @JoinColumn(name="PARENT_ID")
  private Parent parent;
}

class Application {
  void process() {
    ... building parent and child lists

    for (Parent parent : parents) {
      parentRepo.save(parent);
    }

    // also tried this way when objects were "separated"
    for (Parent parent : parents) {
      parentRepo.save(parent);
      childRepo.saveAll(parent.getChildren());
    }
  }
}

家长与孩子的比例可以达到1:75,可以有大约1,000名家长。当前batch_size设置为80。Spring Data版本为2.7.2,使用Hibernate 5.6.10.Final。我知道他们很老了,这是一个遗留项目:/
我期望75个子元素的插入在一个批处理中执行。

o8x7eapl

o8x7eapl1#

在我的例子中,问题是Child类中的这行代码:

@Column(name="PARENT_ID", insertable=false, updatable=false)
  private String parentId;

我只是忘记了当你解除父对象和子对象的关联时,你需要自己管理外键。因此,有insertable=false实际上会导致外键为空(该字段不包含在生成的insert语句中)。删除了这段代码后,一切都按预期工作。
没有一种方法可以使用Spring JPA在一对多关系(或任何其他关系)中的子对象上自动触发saveAll。唯一的方法是删除子对象和父对象中的关系注解和Map注解,并分别保存它们。

相关问题