【发布时间】:2021-03-25 14:25:57
【问题描述】:
我使用 MySQL 作为我的后端,我查看了Hibernate disabled insert batching when using an identity identifier generator 的帖子,发现使用GenerationType.IDENTITY 批量插入不是一个可行的选项
还认为GenerationType.TABLE 性能不佳,基于此article & GenerationType.SEQUENCE 不可行,因为 MySQL 不支持序列。
我的应用大量使用 Spring 数据 JPA,并且大多数主键是通过 MySQL 的 AUTO_INCREMENT 生成的,并在实体中使用 IDENTITY 策略进行映射。我有批量插入记录的用例(通常 500 条记录到最多 10000 条)。我已经看到有关使用 jOOQ 的建议,并希望避免为此目的引入一个全新的框架。
作为一种变通方法,我想出了自己的自定义解决方案,虽然不是最优雅的。一些初步测试表明,与JpaRepository.saveAll()(没有批处理)相比,它的执行速度更快,但我可能忽略了其他影响。这会比根本没有批处理更好吗?
公开批量插入选项的新界面:
public interface MyCustomRepository {
void bulkInsert(List<MyEntity> entities);
}
public interface MyRepository extends JpaRepository<MyEntity, Long>, MyCustomRepository {
}
public class MyCustomRepositoryImpl implements MyCustomRepository {
@PersistenceContext
private EntityManager em;
@Transactional
@Override
public void bulkInsert(List<MyEntity> entities) {
List<List<MyEntity>> batchedList = Lists.partition(entities, batchSize);
batchedList.stream().forEach(list -> {
StringBuffer builder = new StringBuffer();
builder.append("INSERT into my_entity (column1, column2, column3) values ");
builder.append(list.stream().map(myEntity -> {
StringBuilder builder1 = new StringBuilder();
builder1.append("(");
builder1.append(myEntity.getColumn1() + ",");
builder1.append(myEntity.getColumn2() + ",");
builder1.append(myEntity.getColumn3());
builder1.append(")");
return builder1.toString();
}).collect(Collectors.joining(", ")));
em.createNativeQuery(builder.toString()).executeUpdate();
});
}
}
【问题讨论】:
标签: mysql hibernate jpa spring-data-jpa