2、yaml/properties加上配置
spring.jpa.properties.hibernate.jdbc.batch_size: 2000
spring.jpa.properties.hibernate.jdbc.batch_versioned_data: true
spring.jpa.properties.hibernate.order_inserts: true
spring.jpa.properties.hibernate.order_updates: true
spring.jpa.properties.hibernate.generate_statistics: false
3、BatchRepository
@Slf4j
@Repository
public class BatchRepository {
@PersistenceContext
protected EntityManager entityManager;
* Spring Data JPA调用的是Hibernate底层的实现。每次批量保存时,攒够 batchSize 条记录再集中em.flush(),
* @see org.hibernate.cfg.BatchSettings#STATEMENT_BATCH_SIZE
@Value("${spring.jpa.properties.hibernate.jdbc.batch_size}")
private Integer batchSize;
* @see org.hibernate.cfg.BatchSettings#BATCH_VERSIONED_DATA
@Value("${spring.jpa.properties.hibernate.jdbc.batch_versioned_data}")
private String batchVersionedData;
* @see org.hibernate.cfg.BatchSettings#ORDER_INSERTS
@Value("${spring.jpa.properties.hibernate.order_inserts}")
private String orderInserts;
* @see org.hibernate.cfg.BatchSettings#ORDER_UPDATES
@Value("${spring.jpa.properties.hibernate.order_updates}")
private String orderUpdates;
public EntityManager getEntityManager() {
return entityManager;
@PostConstruct
public void init() {
log.info("BaseDao初始化加载。batchSize:{},batchVersionedData:{},orderInserts:{},orderUpdates:{}",
batchSize, batchVersionedData, orderInserts, orderUpdates);
* 批量 insert,实现了性能呈倍提升。注意: <br>
* 1. 需要配置 {@link #batchSize},且jdbc.url开启rewriteBatchedStatements为true <br>
* 2. 关于rewriteBatchedStatements,可参考MySQL官网解释:{@linkplain 'https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-performance-extensions.html#cj-conn-prop_rewriteBatchedStatements'}
* 3. 主键不能用生成策略,否则会报:{@link org.springframework.dao.InvalidDataAccessApiUsageException}: detached entity passed to persist
* @param entities 实体对象列表
* @param <T> 实体类型(必须有@Entity注解)
* @see #batchSize
@Transactional(rollbackFor = Exception.class)
public <T> void batchInsert(List<T> entities) {
if (entities == null || entities.isEmpty()) {
return;
for (T entity : entities) {
entityManager.persist(entity);
* 批量update ( 通过Hibernate进行实现 )
* @param entities 实体对象列表
* @param <T> 实体类型(必须有@Entity注解)
* @see #batchSize
@Transactional(rollbackFor = Exception.class)
public <T> void batchUpdate(List<T> entities) {
if (entities == null || entities.isEmpty()) {
return;
Session session = this.entityManager.unwrap(Session.class);
session.setJdbcBatchSize(batchSize);
for (T t : entities) {
session.update(t);
4、性能验证
写入1000条
1000条逐条save耗时:55秒
saveAll:22秒
batchInsert(rewriteBatchedStatements=false): 10秒
batchInsert(rewriteBatchedStatements=true且开启第2步里的配置): 0.39秒
可见开启与不开启的性能差距达几十倍以上。