1

For background, I am trying to speed up database inserts by enabling hibernate.jdbc.batch_size property. I have added this property, but it appears that the inserts were still not optimized. I have researched and found that the batch_size property should be used in conjunction with JpaRepository.saveAll method.

The problem is that when I save the parent object, it does not trigger a "saveAll" operation on the child list. And when I try to save them separately, I get a constraint violation on the foreign key in the child object.

I have tried to separate the objects (removing the relationship) and saving them individually. However, when I do this, I am getting an "On release of batch it still contained JDBC statements" followed by a "cannot insert NULL into (child_object.foreign_key)".

Here is a snippet of the objects and how they are setup:

@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());
    }
  }
}

Parent to child ratio can be up to 1:75 and there can be about 1,000 parents. Current batch_size is set to 80. Spring Data version is 2.7.2 and using Hibernate 5.6.10.Final. I know they're old, it's a legacy project :/

I am expecting for the inserts of the 75 children to execute in one batch.

Jordan
  • 11
  • 2

1 Answers1

0

In my case the issue was with this line of code in the Child class:

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

I simply forgot that when you disassociate the parent and child objects you need to manage the foreign keys yourself. So, having insertable=false was literally causing the foreign key to be null (that field was not included in the resulting insert statement). After removing that bit of code, everything worked as expected.

There isn't a way to automatically trigger saveAll on child objects in a one-to-many relationship (or any other relationship) using Spring JPA. The only way to do this is to remove the relationship annotation and mapping annotation in the child and parent objects and save them separately.

Jordan
  • 11
  • 2