一、前言
今天小編帶大家一起整合一下easyExcel,之所以用這個,是因為easyExcel性能比較好,不會報OOM!
市面上常見的匯入匯出Excel分為三種:
- hutool
- easyExcel
- poi
hutool和easyExcel都是對poi的封裝,使用起來更加方便!
如果想使用poi和hutool匯出的可以看一下小編的之前寫的文章:
使用POI+hutool匯入Excel
使用POI把查詢到的資料表資料匯出到Excel中,一個表一個sheet
匯出的話看一下這篇,下面主要以匯入來展開介紹!
EasyExcel匯出Excel表格到瀏覽器,并通過Postman測驗匯出Excel
二、匯入依賴
小編這里是3.0.X版本的,版本不同可能導致部分有出入,如果大家版本是3.1.X,可以去官方檔案看看有不一樣的!
官方檔案
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>
三、物體類
這里可以自帶的轉換器:
- @DateTimeFormat("yyyy年MM月dd日HH時mm分ss秒")
- LocalDateTimeStringConverter
或者自定義轉化器:
實作:implements Converter<T>
具體檔案:官方檔案
@ExcelProperty引數注意:
這里不建議 index 和 name 同時用,要么一個物件只用index,要么一個物件只用name去匹配
用名字去匹配,這里需要注意,如果名字重復,會導致只有一個欄位讀取到資料
/**
* @author wangzhenjun
* @date 2022/12/2 15:52
*/
@Data
public class Test {
@TableId
private Integer id;
@ExcelProperty(index = 0)
private String name;
@ExcelProperty(index = 1)
private Integer age;
@ExcelProperty(index = 2,converter = LocalDateTimeStringConverter.class)
private LocalDateTime time;
}
四、撰寫監聽器
注意點:
這個監聽器一定不要是單例的,被spring管理默認為單例,如果要使用@Component,一定要加上:
@Scope("prototype"),這樣在創建完后spring不會進行管理,每次都會是新bean!
不加@Component在匯入時要進行new ImportDataListener !
小編這里不想new了直接這樣寫!!如果不想這樣,可以使用構造器set進行使用!
BATCH_COUNT :資料閾值,超過了就會清理list,在之前可以進行保存到資料庫中,方便記憶體回收,防治OOM!
這里保存到資料庫中一般使用批量保存,不要決議到一行就去保存資料庫中,這樣資料量大會給資料庫增加IO,導致掛掉!這里小編使用ServiceImpl的saveBatch()方法,也可以自己寫一下,像小編這樣寫,會出現回圈依賴,加上@Lazy就行!
/**
* @author wangzhenjun
* @date 2022/12/2 15:38
*/
@Slf4j
@Component
// 每次bean都是新的,不要單例
@Scope("prototype")
public class ImportDataListener implements ReadListener<Test> {
@Autowired
@Lazy
private TestService testService;
/**
* 每隔5條存盤資料庫,實際使用中可以100條,然后清理list ,方便記憶體回收
*/
private static final int BATCH_COUNT = 100;
/**
* 快取的資料
*/
private List<Test> importExcelDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* 這個每一條資料決議都會來呼叫
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(Test data, AnalysisContext context) {
log.info("決議到一條資料:{}", JSON.toJSONString(data));
importExcelDataList.add(data);
// 達到BATCH_COUNT了,需要去存盤一次資料庫,防止資料幾萬條資料在記憶體,容易OOM
if (importExcelDataList.size() >= BATCH_COUNT) {
saveData();
// 存盤完成清理 list
importExcelDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* 所有資料決議完成了 都會來呼叫
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 這里也要保存資料,確保最后遺留的資料也存盤到資料庫
saveData();
log.info("所有資料決議完成!");
}
/**
* 加上存盤資料庫
*/
private void saveData() {
log.info("{}條資料,開始存盤資料庫!", importExcelDataList.size());
testService.saveBatch(importExcelDataList);
log.info("存盤資料庫成功!");
}
}
五、Controller
/**
* @author wangzhenjun
* @date 2022/10/26 16:51
*/
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private TestService testService;
@PostMapping("/import")
public Result importExcel(@RequestBody MultipartFile multipartFile){
testService.importExcel(multipartFile);
return Result.success("ok");
}
}
六、Service
/**
* @author wangzhenjun
* @date 2022/10/26 16:55
*/
public interface TestService extends IService<Test> {
void importExcel(MultipartFile multipartFile);
}
七、ServiceImpl
/**
* @author wangzhenjun
* @date 2022/10/26 16:56
*/
@Service
public class TestServiceImpl extends ServiceImpl<TestDbMapper, Test> implements TestService{
@Autowired
private ImportDataListener importDataListener;
@SneakyThrows
@Override
public void importExcel(MultipartFile multipartFile) {
InputStream inputStream = multipartFile.getInputStream();
// 這里 需要指定讀用哪個class去讀,然后讀取第一個sheet 檔案流會自動關閉
EasyExcel.read(inputStream, Test.class, importDataListener).sheet().doRead();
}
}
八、Mapper
/**
* @author wangzhenjun
* @date 2022/10/26 17:07
*/
public interface TestDbMapper extends BaseMapper<Test> {
}
九、測驗
準備Excel資料:

postman上傳:

控制臺列印:

資料庫查看:

完美搞定!!
十、總結
這樣就完成了easyExcel批量匯入Excel到資料庫,還是有很多要注意的點:
- 自定義轉換器
- 監聽器不要單例
- 保存資料庫采用批量
- 版本差距
如果對你有幫助,還請不要吝嗇您的發財小手,你的一鍵三連是我寫作的動力,謝謝大家哈!!
可以看下小編的微信公眾號,文章首發看,歡迎關注,一起交流哈!!

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/541713.html
標籤:其他
上一篇:JDBC
