Spring 使用 OneToMany 层次结构批量批量插入

Spring Batch Bulk Insert with OneToMany Hierarchy

我正在使用 spring 批处理来读取和转换树状实体并使用 JpaItemWriter 写入 oracle 数据库。对于树状实体,我的意思是:

class A {
    @OneToMany
    List<B> bList;
}

class B {
    @OneToMany
    List<C> cList;
}

class C {
    @OneToMany
    List<D> dList;
}

class D {

}

关系的大小可以快速增长,但出于业务原因需要在一次事务中同时保留整个实体。有了这个 4 级层次结构,我想知道是否可以使用一些 Hibernate(JPA 首选)方法在自上而下的策略中调用批量插入,使用 spring JpaItemWriter 来持久化所有 "B" 实体一次调用数据库,然后调用所有 "C" 个实体,依此类推......而不是像我的调试日志显示的那样为每个实体插入一个。先谢谢您的帮助。

简短的回答是,如果您将 Hibernate 用于 ORM 实现,应该是可能的。

Hibernate 文档在某种程度上深入研究了批处理 here。如果配置正确,Hibernate 将尝试在每个 flush()(每个块的末尾)期间按实体类型对您的插入和更新进行排序。

您还需要确保设置了以下属性并且您没有为您的 ID 使用 IDENTITY 生成器:

<prop key="hibernate.jdbc.batch_size">50<!--or some other number--></prop>
<prop key="hibernate.order_inserts">true</prop>
<prop key="hibernate.order_updates">true</prop>
<prop key="hibernate.jdbc.batch_versioned_data">true</prop>

本文 Red Hat example 说明如何使用持久性单元做同样的事情。

现在,综上所述,Hibernate 可能很敏感,因此您可能想要增加 BatchingBatcher class 的日志记录以确认它实际上正在对您的插入进行批处理。最后,注意任何不使用序列的实体中的 saveOrUpdate() 方法。如果你正在定义你自己的 ID 而你的对象还没有在会话中(它不会),Hibernate 将首先对数据库发出 select 以确定是 insert 还是 update 是必需的。