如何使用 Spring-Batch 批量插入?

How to bulk insert with Spring-Batch?

我正在尝试使用 spring-batch 进行 bulk/batch 插入。

public ItemWriter<MyEntity> jpaItemWriter() {
    LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(ds);
    builder.addAnnotatedClasses(MyEntity.class);
    builder.setProperty("hibernate.show_sql", "true");
    builder.setProperty("hibernate.batch_size", "20");
    builder.setProperty("hibernate.order_updates", "true");
    builder.setProperty("hibernate.order_inserts", "true");
    HibernateItemWriter<MyEntity> writer = new HibernateItemWriter<>();
    writer.setSessionFactory(builder.buildSessionFactory());
    return writer;
}

结果: 我只得到单个 insert 语句,而不是批量插入!我可以从 hibernate + on postgresql 级别的日志中看到它。为什么批量插入不起作用?

更新:

@Entity
public class MyEntity {
    @Id
    String shortname;
    String fullname;
}

Spring 与 SQL 语句批处理无关,它全部由 Hibernate 管理。
我看到您已启用并正确配置了批处理,但这还不足以使其正常工作……您还需要使用正确的会话类型。在休眠中有两种会话类型:有状态会话和无状态会话。
stateful session,通过

获得
sessionFactory.openSession();

并且如果使用@Transactional 也默认使用,从不使用批处理(即使已配置)并在事务提交时立即发送所有 SQL 语句。但是,您可以通过不时调用 flush() 来模拟批处理,并且 SQL 语句将在每次 flush() 时发送到数据库。

无状态会话,通过

获得
sessionFactory.openStatelessSession();

尊重批处理配置,因此只需切换到 stateless 会话,批处理将按预期工作。 Hibernate 将记录每个 session.insert(),但不会将 SQL 插入语句发送到数据库,而是将 SQL 插入语句作为配置大小的批次发送。所以最好"tail -f"数据库日志。 有两种会话类型的主要思想是,stateful 会话使用缓存,每个保存的实体最终都在一级缓存中,因此如果您保存 100k 个实体,您将得到 OOM .解决方案是使用不与任何级别缓存交互的 stateless 会话。 您可以阅读有关 stateless session.

的更多信息