一:在run()方法里寫插入
1 package com.smartdata.pms.thread; 2 3 import com.smartdata.pms.entity.PmsProduct; 4 import com.smartdata.pms.mapper.PmsProductMapper; 5 import lombok.extern.slf4j.Slf4j; 6 7 import java.util.List; 8 9 /** 10 * @ProjectName: smartdata 11 * @Package: com.smartdata.pms.thread 12 * @ClassName: InsertBatchRun 13 * @Author: heluwei 14 * @Description: 15 * @Date: 2020/3/22 16:36 16 * @Version: 1.0 17 */ 18 @Slf4j 19 public class InsertBatchRun implements Runnable { 20 //數據層訪問 21 private PmsProductMapper pmsProductMapper; 22 //具體插入批次 23 private int batch; 24 25 //插入的數據 26 private List<PmsProduct> list; 27 28 public InsertBatchRun(PmsProductMapper pmsProductMapper,List<PmsProduct> list,int batch) { 29 this.pmsProductMapper = pmsProductMapper; 30 this.list = list; 31 this.batch = batch; 32 } 33 @Override 34 public void run() { 35 try { 36 for(int i=0;i<list.size();i++){ 37 this.pmsProductMapper.insert(list.get(i)); 38 } 39 log.info("第" + this.batch + "批次插入成功"); 40 } catch (Exception e) { 41 log.error("第" + this.batch + "批次插入失敗"); 42 } 43 44 } 45 }
注意:在使用***Mapper的時候。不能使用@Autowired,因為多線程環境下,防止注入。
二:使用線程池
1 package com.smartdata.pms.utils; 2 3 import com.smartdata.pms.entity.PmsProduct; 4 import com.smartdata.pms.mapper.PmsProductMapper; 5 import com.smartdata.pms.thread.InsertBatchRun; 6 import lombok.extern.slf4j.Slf4j; 7 8 import java.util.List; 9 import java.util.concurrent.ArrayBlockingQueue; 10 import java.util.concurrent.ThreadPoolExecutor; 11 import java.util.concurrent.TimeUnit; 12 13 /** 14 * @ProjectName: smartdata 15 * @Package: com.smartdata.pms.utils 16 * @ClassName: ExecutorUtils 17 * @Author: heluwei 18 * @Description: 19 * @Date: 2020/3/22 16:39 20 * @Version: 1.0 21 */ 22 @Slf4j 23 public class ExecutorUtils { 24 private static final int CORE_POOL_SIZE = 5; //核心線程數為 5 25 private static final int MAX_POOL_SIZE = 10; //最大線程數 10 26 private static final int QUEUE_CAPACITY = 100; // 27 private static final Long KEEP_ALIVE_TIME = 1L; //當線程數大於核心線程數時,多余的空閑線程存活的最長時間 28 29 public static void executeThreadPool(PmsProductMapper pmsProductMapper, List<PmsProduct> pmsProductList){ 30 //使用阿里巴巴推薦的創建線程池的方式 31 //通過ThreadPoolExecutor構造函數自定義參數創建 32 ThreadPoolExecutor executor = new ThreadPoolExecutor( 33 CORE_POOL_SIZE, 34 MAX_POOL_SIZE, 35 KEEP_ALIVE_TIME, //當線程數大於核心線程數時,多余的空閑線程存活的最長時間 36 TimeUnit.SECONDS, //時間單位 37 new ArrayBlockingQueue<>(QUEUE_CAPACITY), //任務隊列,用來儲存等待執行任務的隊列 38 new ThreadPoolExecutor.CallerRunsPolicy()); //飽和策略,簡單點說就是后面排隊的線程就在那兒等着。 39 //被拒絕的任務在主線程中運行,所以主線程就被阻塞了,別的任務只能在被拒絕的任務執行完之后才會繼續被提交到線程池執行 40 long start = System.currentTimeMillis(); 41 //計數器 42 int size = 0; 43 for (int i = 0; i < (Math.round((pmsProductList.size() / 2000)+0.5)); i++) { 44 int startLen = i * 2000; 45 int endLen = ((i + 1) * 2000 > pmsProductList.size() ? pmsProductList.size() - 1 : (i + 1) * 2000); 46 List<PmsProduct> threadList = pmsProductList.subList(startLen, endLen); 47 size = size + threadList.size(); 48 executor.execute(new InsertBatchRun(pmsProductMapper, threadList, i)); 49 } 50 System.err.println("插入數據總條數:" + size); 51 long end = System.currentTimeMillis(); 52 log.error("查詢耗時:" + (end - start)); 53 54 //終止線程池 55 // void shutdown() 啟動一次順序關閉,執行以前提交的任務,但不接受新任務。若已經關閉,則調用沒有其他作用。 56 executor.shutdown(); 57 //boolean isTerminated() 58 //若關閉后所有任務都已完成,則返回true。注意除非首先調用shutdown或shutdownNow,否則isTerminated永不為true。 59 while (!executor.isTerminated()) { 60 //System.out.println("線程池還沒有完全關閉!!!"); 61 } 62 log.info("插入完成:"+(end - start)); 63 } 64 }
三:要導入的信息
1 @SysLog("導入商品") 2 @PostMapping("importProduct") 3 public R importProduct(@RequestParam(value = "file", required = false) MultipartFile excelFile) { 4 //============================使用模板====================================================== 5 InputStream inputStream = null; 6 try { 7 // 使用模板導入——接收上傳文件 8 inputStream = excelFile.getInputStream(); 9 // 讀取表格數據 10 List<PmsProduct> pmsProductList = EasyExcel.read(inputStream, PmsProduct.class, null).headRowNumber(1).sheet(0).doReadSync(); 11 // TODO 根據業務處理objectList…… 12 ExecutorUtils.executeThreadPool(pmsProductMapper,pmsProductList); 13 /*pmsProductList.forEach(pmsProduct -> { 14 pmsProductService.save(pmsProduct); 15 });*/ 16 } catch (IOException e) { 17 e.printStackTrace(); 18 } finally { 19 if (inputStream != null) { 20 try { 21 inputStream.close(); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 } 25 } 26 } 27 return new R(); 28 }
四:對應的實體類
1 package com.smartdata.pms.entity; 2 3 import com.alibaba.excel.annotation.ExcelIgnore; 4 import com.alibaba.excel.annotation.ExcelProperty; 5 import com.alibaba.excel.annotation.write.style.ColumnWidth; 6 import com.baomidou.mybatisplus.annotation.IdType; 7 import com.baomidou.mybatisplus.annotation.TableId; 8 import com.baomidou.mybatisplus.annotation.TableLogic; 9 import com.baomidou.mybatisplus.annotation.TableName; 10 import com.baomidou.mybatisplus.extension.activerecord.Model; 11 import com.fasterxml.jackson.databind.annotation.JsonSerialize; 12 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; 13 import lombok.Data; 14 import lombok.EqualsAndHashCode; 15 16 import java.time.LocalDateTime; 17 18 /** 19 * @ProjectName: smartdata 20 * @Package: com.smartdata.pms.entity 21 * @ClassName: PmsProduct 22 * @Author: heluwei 23 * @Description: 商品列表 24 * @Date: 2019/12/29 15:03 25 * @Version: 1.0 26 */ 27 @Data 28 @EqualsAndHashCode(callSuper = true) 29 @TableName("pms_product") 30 public class PmsProduct extends Model<PmsProduct> { 31 private static final long serialVersionUID = 1L; 32 @TableId(value = "pro_id", type = IdType.AUTO) 33 @JsonSerialize(using = ToStringSerializer.class)//解決long精度丟失問題 34 @ExcelProperty(value = "序號",index = 0) 35 @ColumnWidth(35) 36 private Long proId; //商品ID 37 38 @ExcelProperty(value = "商品編號",index = 1) 39 @ColumnWidth(35) 40 private String proNo; //商品名稱 41 42 @ExcelProperty(value = "商品名稱",index = 2) 43 @ColumnWidth(35) 44 private String proName; //商品編號 45 46 @ExcelProperty(value = "商品價格",index = 3) 47 @ColumnWidth(35) 48 private Float proPrice; //商品價格 49 50 @ExcelProperty(value = "商品類別",index = 4) 51 @ColumnWidth(35) 52 private Long proCategoryId; //商品類別 53 54 @ExcelProperty(value = "商品描述",index = 5) 55 @ColumnWidth(35) 56 private String proDescription; //商品描述 57 58 @ExcelProperty(value = "商品圖片路徑",index = 6) 59 @ColumnWidth(35) 60 private String proImage; //商品圖片路徑 61 62 @ExcelProperty(value = "商品庫存",index = 7) 63 @ColumnWidth(35) 64 private Long proInventory ; //商品庫存 65 66 @ExcelProperty(value = "商品銷量",index = 8) 67 @ColumnWidth(35) 68 private Long proSail; //商品銷量 69 70 @ExcelProperty(value = "商品規格",index = 9) 71 @ColumnWidth(35) 72 private String proSize; //商品規格 73 74 @ExcelProperty(value = "是否熱銷",index = 10) 75 @ColumnWidth(35) 76 private String IsHot; //是否熱銷 0是 ,-1不是 77 78 @ExcelProperty(value = "是否推薦",index = 11) 79 @ColumnWidth(35) 80 private String IsReconnend; //是否推薦 0是,-1不是 81 82 @ExcelIgnore 83 private LocalDateTime proCreateTime; //上架時間 84 @ExcelIgnore 85 private LocalDateTime proUpdateTime; 86 /** 87 * 是否刪除 -1:已刪除 0:正常 88 */ 89 @TableLogic 90 @ExcelIgnore 91 private String delFlag; 92 }
Excel表:
在使用Math.ceil()函數的時候。5.013給我計算成了5.我想保存的是6.
解決方案:用四舍五入函數+0.5
double ceil = Math.round(5.013+0.5);輸出6.
五:前台
1 //指定允許上傳的文件類型 2 upload.render({ 3 elem: '#importFile' 4 ,url: '/pms/pmsPro/importProduct' 5 , method: 'POST' 6 ,accept: 'file' //普通文件 7 ,exts: 'xlsx' //只允許上傳壓縮文件 8 , headers: { 9 Authorization: 'Bearer ' + access_token, 10 } 11 ,done: function(res){ 12 layer.msg(res.msg); 13 layui.table.reload('lay-Product-list'); //重載表格 14 } 15 });