如何使用 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.
的更多信息
我正在尝试使用 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.
的更多信息