如何批量插入Spring-Batch?

时间:2015-01-09 08:28:05

标签: java spring hibernate spring-batch

我尝试使用spring-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语句,而不是批量插入!我可以在postgresql级别的hibernate +日志中看到它。为什么批量插入不起作用?

更新

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

1 个答案:

答案 0 :(得分:3)

Spring与SQL语句批处理无关,它全部由Hibernate管理。
我看到你已经启用了批处理并且配置正确,但这还不足以让它工作......你还需要使用正确的会话类型。在hibernate中有两种会话类型:有状态会话和无状态会话。
有状态会话,使用

获得
sessionFactory.openSession();

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

无状态会话,使用

获得
sessionFactory.openStatelessSession();

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

的更多信息