日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java jpa saveall方法优化_JPA批量插入(saveAll)

發布時間:2023/12/3 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java jpa saveall方法优化_JPA批量插入(saveAll) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有時候要從第三方導入數據,一般量都比較大,除了方法用異步線程@Async之外,如果每條記錄都調用一次save顯然對數據庫壓力很大。可以使用JPA的批量保存方法saveAll(Iterable entities)。

由于JPA的批量保存和批量修改是同一個方法,所以本文也適用批量修改操作。

一、Entity改造

增加3個注解,方便在Controller類build方式構造對象。

@Builder

@NoArgsConstructor

@AllArgsConstructor

完整注解:

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

@ApiModel("休息日,休息日可能不處理業務,備用")

@Entity

@Table(name = "bz_setup_restday", schema = "bankrouter")

public class BzSetupRestdayEntity implements Serializable {

......

二、Repository

package com.pay.payee.repository;

import com.pay.payee.entity.BzSetupRestdayEntity;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Date;

/**

*

休息日,休息日可能不處理業務,備用(BzSetupRestday)表數據庫訪問層

*

* @author 郭秀志 jbcode@126.com

* @since 2020-05-08 23:50:43

*/

public interface BzSetupRestdayRepository extends JpaRepository {

}

三、Service實現類

關鍵方法saveAll(Iterable entities)。

package com.pay.payee.service.impl;

import com.pay.payee.entity.BzSetupRestdayEntity;

import com.pay.payee.repository.BzSetupRestdayRepository;

import com.pay.payee.service.IBzSetupRestdayService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.util.Date;

import java.util.List;

import java.util.Optional;

/**

*

休息日,休息日可能不處理業務,備用(BzSetupRestday)表服務實現類

*

* @author 郭秀志 jbcode@126.com

* @since 2020-05-08 23:50:43

*/

@Service("bzSetupRestdayService")

public class BzSetupRestdayServiceImpl implements IBzSetupRestdayService {

@Autowired

private BzSetupRestdayRepository bzSetupRestdayRepository;

@Override

public void save(BzSetupRestdayEntity bzSetupRestdayEntity) {

bzSetupRestdayRepository.save(bzSetupRestdayEntity);

}

public List saveAll(Iterable entities) {

return bzSetupRestdayRepository.saveAll(entities);

}

}

四、Controller

60000條數據使用方法saveAll(Iterable entities)進行批量保存。

package com.pay.payee.controller;

import com.pay.payee.entity.BzSetupRestdayEntity;

import com.pay.payee.service.IBzSetupRestdayService;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

/**

* 休息日,休息日可能不處理業務,備用(BzSetupRestday)表控制層

*

* @author 郭秀志 jbcode@126.com

* @since 2020-05-08 23:50:43

*/

@RestController

@RequestMapping("/bzSetupRestday")

public class BzSetupRestdayController {

/**

* 服務對象

*/

@Resource

private IBzSetupRestdayService bzSetupRestdayService;

/*

* @Description 批量保存

* @Param [entities]

* @return java.util.List

*/

@GetMapping("/saveAll")

public List saveAll() {

long begin = System.currentTimeMillis();

List list = new ArrayList();

for (int i = 0; i < 60000; i++) {

BzSetupRestdayEntity build = BzSetupRestdayEntity.builder().groupId("1").restDate(new Date()).useType("2").build();

list.add(build);

}

List sList = (List) bzSetupRestdayService.saveAll(list);

long end = System.currentTimeMillis();

System.out.println("時長:" + (end - begin));

return sList;

}

}

五、調用url測試

http://localhost:8555/bzSetupRestday/saveAll

控制臺輸出耗時(毫秒):時長:15958

網上個別人遇到saveAll速度慢,添加了如下配置信息解決。我實測速度無差別。

spring:

jpa:

properties:

hibernate:

#打印執行時間統計信息

generate_statistics: true

jdbc:

#每批500條提交

batch_size: 500

batch_versioned_data: true

order_inserts: true

order_updates: true

六、批量保存優化

6.1 背景

有次實踐是有20萬左右的數據要批量的插入,速度非常慢,發現打印出來的sql是先select一次,再insert。

6.2 速度慢原因

原生的saveAll()方法可以保證程序的正確性,但是如果數據量比較大效率低,看下源碼就知道其原理是 for 循環每一條數據,然后先select一次,如果數據庫存在,則update。如果不存在,則insert。

6.3. saveAll源碼

SimpleJpaRepository的saveAll(Iterable entities)方法源碼如下:

@Transactional

public List saveAll(Iterable entities) {

Assert.notNull(entities, "Entities must not be null!");

List result = new ArrayList();

Iterator var3 = entities.iterator();

while(var3.hasNext()) {

S entity = var3.next();

result.add(this.save(entity));//save方法是核心邏輯

}

return result;

}

@Transactional

public S save(S entity) {

if (this.entityInformation.isNew(entity)) {

this.em.persist(entity);

return entity;

} else {

return this.em.merge(entity);

}

}

6.4 解決方案

6.4.1 批量插入

解決方案是自己用em進行持久化插入,省了一步查詢操作。

@PersistenceContext

private EntityManager entityManager;

@Override

@Transactional(rollbackFor = Exception.class)

public void addBatch(List list) {

for (ProjectApplyDO projectApplyDO : list) {

entityManager.persist(projectApplyDO);//insert插入操作

}

entityManager.flush();

entityManager.clear();

}

6.4.2 批量更新

在確保數據已經存在的情況下,如果是批量更新可以如下代碼代替上面的entityManager.persist(projectApplyDO);語句:

entityManager.merge(projectApplyDO);//update更新操作

總結

以上是生活随笔為你收集整理的java jpa saveall方法优化_JPA批量插入(saveAll)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。