通过easyexcel实现数据导入功能

news/2024/12/22 21:20:16/

上一篇文章通过easyexcel导出数据到excel表格已经实现了简单的数据导出功能,这篇文章也介绍一下怎么通过easyexcel从excel表格中导入数据。

目录

一、前端代码

index.html

index.js

二、后端代码

controller

service

SongServiceImpl

三、功能预览

四、后端代码改进

频繁访问数据库问题


首先,需要在实体类中添加需要导出的字段,@ExcelIgnore注解表示该字段不会被导出到excel,当然,导入的时候也不会读这个字段。

package com.example.springboot.entity;import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;import java.io.Serializable;
import java.time.LocalDateTime;/*** 歌曲* @author heyunlin* @version 1.0*/
@Data
@TableName("song")
public class Song implements Serializable {private static final long serialVersionUID = 18L;@ExcelProperty("歌曲编号")@TableId(type = IdType.INPUT)private String id;/*** 歌曲名*/@ExcelProperty("歌曲名")private String name;/*** 歌手*/@ExcelProperty("歌手")private String singer;/*** 描述信息*/@ExcelProperty("描述信息")private String note;/*** 最后一次修改时间*/@ExcelIgnore@TableField("last_update_time")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")private LocalDateTime lastUpdateTime;
}

一、前端代码

在之前的easyui-crud项目的基础上修改,切换到最新代码分支springboot-crud2.0

springboot+mybatis实现增删查改的入门项目。icon-default.png?t=N7T8https://gitee.com/he-yunlin/springboot-crud.git在原来的页面上添加一个对话框,对话框内放一个easyui的filebox,同时,让filebox镶嵌在一个form表单内,因为要对该表单进行必填验证,只有选择了文件才能点击上传按钮。

index.html

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>easyui crud应用</title><link rel="stylesheet" href="/css/themes/icon.css" /><link rel="stylesheet" href="/css/themes/default/easyui.css" /><script src="/js/jquery.min.js"></script><script src="/js/jquery.easyui.min.js"></script><script src="/js/easyui-lang-zh_CN.js"></script><script src="/js/datagrid-filter.js"></script><script src="/js/index.js"></script></head><body><div id="import_dialog" style="display:none;"><form id="import_form"><table style="border-spacing:5px;"><tr><td>上传文件:</td><td><input id="select_file" /></td></tr><tr><td>文件名称:</td><td><div id="file-name"></div></td></tr><tr><td>文件大小:</td><td><div id="file-size"></div></td></tr></table></form></div><table id="song_list"></table></body>
</html>

index.js

在原来的js代码中添加以下代码,这里渲染了刚刚在页面中添加的对话框和输入框,然后在表格的头部工具栏中添加了一个导入按钮。

let form = new FormData();function importHandler() {requestUrl = "/song/import";$("#file-name").empty();$("#file-size").empty();$("#import_dialog").dialog("open");
}$(document).ready(function() { $("#select_file").filebox({buttonText: "选择文件",width: 200,required: true,onChange: function() {let file = $(this).context.ownerDocument.activeElement.files[0];form.append("file", file);$("#file-name").html(file.name);$("#file-size").html((file.size / 1024).toFixed(1) + "KB");}})$("#import_dialog").dialog({title: "数据导入",modal: true,closed: true,closable: true,draggable: false,buttons: [{iconCls: "icon-ok",text: "导入",handler: function() {let bool = $("#import_form").form("validate");if (bool) {$.ajax({url: requestUrl,data: form,cache: false,async: true,type: "POST",dataType: "json",processData: false,contentType: false,success: function (response) {$.messager.show({title: "系统消息",timeout: 5000,showType: "slide",msg: response.message,});$("#import_dialog").dialog("close");$("#member_list").datagrid("reload");},error: function (resp) {// 请求有响应if (resp && resp.responseJSON) {let response = resp.responseJSON;let status = resp.status;if (status) {let message;if (status === 404) { // 404 not foundif (response.path) {message = "路径" + response.path + "不存在。";} else {message = response.message;}} else {message = response.message;}$.messager.alert("系统提示", message, "error");console.log("响应状态码:" + status + ", 响应消息:" + message);} else {console.log("请求没有响应状态码~");}} else {console.log("请求无响应~");}}});} else {$.messager.alert("系统提示", "请选择文件", "warning");}}}, {iconCls: "icon-cancel",text: "取消",handler: function() {$("#select_file").filebox("initValue", null);$("#import_dialog").dialog("close");form.delete("file");}}]});let datagrid = $("#song_list").datagrid({url: "/song/selectByPage",title: "歌曲列表",toolbar: [{iconCls: "icon-upload",text: "导入",handler: function() {importHandler();}}],columns: [[{field: "id", title: "id", width: 200},{field: "name", title: "name", width: 200, editor: "textbox"},{field: "singer", title: "singer", width: 200, editor: "textbox"},{field: "note", title: "note", width: 200, editor: "textbox"},{field: "lastUpdateTime", title: "lastUpdateTime", width: 200, sortable: true}]]});});

二、后端代码

controller

在controller中添加一个接口,请求类型为post,路径为/import,因为import是java关键字,所以方法名不能使用import,改成importData。

/*** @author heyunlin* @version 1.0*/
@RestController
@RequestMapping(path = "/song", produces="application/json;charset=utf-8")
public class SongController {private final SongService songService;@Autowiredpublic SongController(SongService songService) {this.songService = songService;}@RequestMapping(value = "/import", method = RequestMethod.POST)public void importData(MultipartFile file) throws IOException {songService.importData(file);}}

service

SongService接口添加importData()方法

/*** @author heyunlin* @version 1.0*/
public interface SongService {void importData(MultipartFile file) throws IOException;
}

SongServiceImpl

通过easyexcel的API读取上传的文件,然后根据读取的结果,判断插入或修改现有数据。

/*** @author heyunlin* @version 1.0*/
@Service
public class SongServiceImpl implements SongService {private final SongMapper songMapper;@Autowiredpublic SongServiceImpl(SongMapper songMapper) {this.songMapper = songMapper;}@Overridepublic void importData(MultipartFile file) throws IOException {EasyExcel.read(file.getInputStream(), Song.class, new ReadListener<Song>() {@Overridepublic void invoke(Song data, AnalysisContext context) {Song song = songMapper.selectById(data.getId());if (song == null) {songMapper.insert(data);} else {songMapper.updateById(data);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {}}).sheet().doRead();}}

三、功能预览

如图,选择文件之后会显示文件的预览信息,点击导入,就会通过ajax上传文件到后台controller接口。

点击导入按钮,后端读取到了表格数据,并在控制台打印。

四、后端代码改进

上面的代码有一个很明显的问题

// 频繁查询数据库,excel表有多少行就查询多少次
Song song = songMapper.selectById(data.getId());

频繁访问数据库问题

对此,需要进行相应的改进,减少查询次数。

最有效的方法是一次性查询所有歌曲,然后以ID为key保存到一个map里,当然,这只适合数据量不是特别大的情况。

优化后的代码如下:

@Override
public void importData(MultipartFile file) throws IOException {// 查询全部歌曲信息List<Song> list = songMapper.selectList(null);// 把歌曲信息以ID为key保存到map中Map<String, Song> map = new HashMap<>(list.size());for (Song song : list) {map.put(song.getId(), song);}// 读excel表EasyExcel.read(file.getInputStream(), Song.class, new ReadListener<Song>() {@Overridepublic void invoke(Song data, AnalysisContext context) {if (map.containsKey(data.getId())) {songMapper.updateById(data);} else {songMapper.insert(data);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {}}).sheet().doRead();
}


http://www.ppmy.cn/news/1231019.html

相关文章

Altium Designer学习笔记2

原理图的绘制 需要掌握的是系统自带原理图库元件的添加。

Keithley2420吉时利2420数字源表

Keithley2420吉时利2420数字源表系列&#xff0c;专用于要求紧密结合源和测量的测试应用。全部数字源表型号都提供精密电压源和电 流源以及测量功能。每款数字源表既是高度稳定的直流 电源也是真仪器级的6位半万用表。此电源的特性包括 低噪声、精密和回读。此万用表的功能包括…

如何利用 AI 写一本书并实现被动收入

如何每个月写一本能赚 5000 美元的书&#xff1f;不少人不知道如何在一周内写作和出版一本书 这里有个教程教你如何利用 AI 写一本书并实现被动收入 [收藏起来以备后用] 推出书友智能写作工具&#xff1a;Bookwiz 不用花几年时间独自写作一本小说&#xff0c;人工智能可以作…

Go语言中获取协程ID

简介 java同事都知道&#xff0c;线程会有对应的id&#xff0c;那么go语言中协程有id吗&#xff0c;其实是有的&#xff0c;但是不建议使用。 实在需要使用的话可以使用本文的例子获取 stack 我们先看一下runtime.Stack打印出来的栈结构&#xff0c;其中就包括了协程id fu…

uniapp和vue3+ts创建自定义下拉选择框组件

使用uniapp开发小程序的时候&#xff0c;使用了uview的ui组件&#xff0c;但是里面没有下拉选择组件&#xff0c;只有Picker 选择器&#xff0c;但是我们想要使用下拉选择的组件&#xff0c;所以需要自定义个一个下拉选择的自定义组件&#xff0c;我就只能自己动手创建这个自定…

《活着》思维导图

今天给大家分享的这部作品的题目叫“活着”&#xff0c;作为一个词语&#xff0c;“活着”在我们中国的语言里充满了力量&#xff0c;它的力量不是来自于喊叫&#xff0c;也不是来自于进攻&#xff0c;而是忍受&#xff0c;去忍受生命赋予我们的责任&#xff0c;去忍受现实给予…

vsto word 获取目录起始页和结束页,如目录起始位置为2、结束位置为3,返回2和3

using Word Microsoft.Office.Interop.Word;namespace VstoWordExample {class Program{static void Main(string[] args){// 请确保你的项目引用了 Microsoft.Office.Interop.Word// 创建 Word 应用程序对象Word.Application wordApp new Word.Application();// 打开文档Wor…

1688商品详情API跨境专用接口php java

一、引言 随着全球电子商务的快速发展&#xff0c;跨境电子商务已经成为一种重要的国际贸易形式。1688作为全球最大的B2B电子商务平台之一&#xff0c;不仅拥有大量的商品资源&#xff0c;还为商家提供了丰富的API接口&#xff0c;以实现更高效、更便捷的电子商务活动。其中&a…