JAVA实现Excel模板导入案例分析
需求:将excel中的所有数据导入到PG数据库的对应数据表中,需要对数据进行校验等操作
maven依赖:
<properties><hutool.version>5.5.1</hutool.version><poi.version>3.17</poi.version></properties><!-- excel工具 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>${poi.version}</version></dependency><!-- hutool相关依赖 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>${hutool.version}</version></dependency>
PG数据表的设计:
CREATE TABLE "public"."shopping_detail" ("id" int8 NOT NULL,"order_id" varchar(50) COLLATE "pg_catalog"."default" NOT NULL,"good_name" varchar(50) COLLATE "pg_catalog"."default" NOT NULL,"address" varchar(255) COLLATE "pg_catalog"."default" NOT NULL,"receiver" varchar(50) COLLATE "pg_catalog"."default","phone" varchar(30) COLLATE "pg_catalog"."default","num" varchar(10) COLLATE "pg_catalog"."default" NOT NULL,"create_by" varchar(30) COLLATE "pg_catalog"."default","create_time" timestamptz(6),"update_by" varchar(30) COLLATE "pg_catalog"."default","update_time" timestamptz(6),"remark" varchar(500) COLLATE "pg_catalog"."default",CONSTRAINT "cgm_drug_info_pkey" PRIMARY KEY ("id")
)
;ALTER TABLE "public"."shopping_detail"OWNER TO "postgres";COMMENT ON COLUMN "public"."shopping_detail"."id" IS '主键ID';COMMENT ON COLUMN "public"."shopping_detail"."order_id" IS '订单号';COMMENT ON COLUMN "public"."shopping_detail"."good_name" IS '商品名称';COMMENT ON COLUMN "public"."shopping_detail"."address" IS '收货地址';COMMENT ON COLUMN "public"."shopping_detail"."receiver" IS '收件人';COMMENT ON COLUMN "public"."shopping_detail"."phone" IS '手机号';COMMENT ON COLUMN "public"."shopping_detail"."num" IS '数量';COMMENT ON COLUMN "public"."shopping_detail"."create_by" IS '创建人(账号name)';COMMENT ON COLUMN "public"."shopping_detail"."create_time" IS '创建时间';COMMENT ON COLUMN "public"."shopping_detail"."update_by" IS '更新人(账号name)';COMMENT ON COLUMN "public"."shopping_detail"."update_time" IS '更新时间';COMMENT ON COLUMN "public"."shopping_detail"."remark" IS '备注';COMMENT ON TABLE "public"."shopping_detail" IS '购买商品详情表';
MyBatisPlus的实体类设计:
package com.opencv.domain.entity;import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;@ApiModel("购买商品详情表")
@TableName(value = "shopping_detail", autoResultMap = true)
public class ShoppingDetailEntity extends CgmBaseEntity {/*** 商品名称*/@ApiModelProperty(value = "商品名称")private String goodName;/*** 收货地址*/@ApiModelProperty(value = "收货地址")private String address;/*** 收件人*/@ApiModelProperty(value = "收件人")private String receiver;/*** 手机号*/@ApiModelProperty(value = "手机号")private String phone;/*** 订单号*/@ApiModelProperty(value = "订单号")private String orderId;/*** 数量*/@ApiModelProperty(value = "数量")private String num;public String getNum() {return num;}public void setNum(String num) {this.num = num;}public String getOrderId() {return orderId;}public void setOrderId(String orderId) {this.orderId = orderId;}public String getGoodName() {return goodName;}public void setGoodName(String goodName) {this.goodName = goodName;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getReceiver() {return receiver;}public void setReceiver(String receiver) {this.receiver = receiver;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}
}
Mapper设计:
package com.opencv.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.opencv.domain.entity.ShoppingDetailEntity;
import org.springframework.stereotype.Repository;@Repository
public interface ShoppingDetailMapper extends BaseMapper<ShoppingDetailEntity> {
}
订单Excel需要导入的数据如下所示:
反射需要用到的枚举类设计:
package com.opencv.enums;public enum ShoppingDetailEnum {GOOD_NAME("商品名称", "goodName"),ADDRESS("收货地址", "address"),RECEIVER("收件人", "receiver"),PHONE("手机号", "phone"),ORDER_ID("订单号", "orderId"),NUM("数量", "num"),;private String columnName;private String fieldName;ShoppingDetailEnum(String columnName, String fieldName) {this.columnName = columnName;this.fieldName = fieldName;}public static ShoppingDetailEnum get(String columnName) {ShoppingDetailEnum[] values = ShoppingDetailEnum.values();for (ShoppingDetailEnum shoppingDetailEnum : values) {if (shoppingDetailEnum.getColumnName().equals(columnName)) {return shoppingDetailEnum;}}return null;}public String getColumnName() {return columnName;}public String getFieldName() {return fieldName;}
}
导入的测试代码(可以改成Web接口的形式对外提供服务),暂时用的main函数的方式实现:
package com.opencv.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.opencv.domain.entity.ShoppingDetailEntity;
import com.opencv.enums.ShoppingDetailEnum;
import com.opencv.mapper.ShoppingDetailMapper;
import com.opencv.utils.ExcelUtil;
import com.opencv.utils.IdUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Rollback
public class ImportExcelDataTests {private static String EXCEL_PATH = "E:\\backUp\\订单数据.xlsx";private static Map<Integer, String> COLUMN_MAP = new HashMap<>();@Autowiredprivate ShoppingDetailMapper shoppingDetailMapper;@Testpublic void importExcelTest() throws Exception {File file = new File(EXCEL_PATH);Workbook workbook = null;try {workbook = new XSSFWorkbook(file);} catch (Exception ex) {workbook = new HSSFWorkbook(new FileInputStream(file));}int numberOfSheets = workbook.getNumberOfSheets();for (int i = 0; i < numberOfSheets; i++) {if (i > 0) {break;}Sheet sheet = workbook.getSheetAt(i);int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();for (int j = 0; j < physicalNumberOfRows; j++) {Row row = sheet.getRow(j);int physicalNumberOfCells = row.getPhysicalNumberOfCells();if (j == 0) {for (int k = 0; k < physicalNumberOfCells; k++) {String cellValue = (String) ExcelUtil.getCellValue(row, k);ShoppingDetailEnum shoppingDetailEnum = ShoppingDetailEnum.get(cellValue);COLUMN_MAP.put(k, shoppingDetailEnum.getFieldName());}continue;// 标题行}ShoppingDetailEntity shoppingDetailEntity = new ShoppingDetailEntity();Field declaredField = null;for (int k = 0; k < physicalNumberOfCells; k++) {String fieldName = COLUMN_MAP.get(k);try {declaredField = shoppingDetailEntity.getClass().getDeclaredField(fieldName);} catch (NoSuchFieldException ex) {// 子类不存在该变量则从父类获取变量declaredField = shoppingDetailEntity.getClass().getSuperclass().getDeclaredField(fieldName);}Object cellValue = ExcelUtil.getCellValue(row, k);declaredField.setAccessible(true);declaredField.set(shoppingDetailEntity, cellValue);}// 开始插入数据LambdaQueryWrapper<ShoppingDetailEntity> shoppingDetailWrapper = new QueryWrapper<ShoppingDetailEntity>().lambda();shoppingDetailWrapper.eq(ShoppingDetailEntity::getOrderId, shoppingDetailEntity.getOrderId());ShoppingDetailEntity searchShoppingDetail = shoppingDetailMapper.selectOne(shoppingDetailWrapper);if (Objects.isNull(searchShoppingDetail)) {ShoppingDetailEntity insertShoppingDetail = new ShoppingDetailEntity();// 这里可以使用beanUtils等工具类通过反射来复制属性值insertShoppingDetail.setId(IdUtils.nextSnowFlakeId());insertShoppingDetail.setAddress(shoppingDetailEntity.getAddress());insertShoppingDetail.setGoodName(shoppingDetailEntity.getGoodName());insertShoppingDetail.setOrderId(shoppingDetailEntity.getOrderId());insertShoppingDetail.setPhone(shoppingDetailEntity.getPhone());insertShoppingDetail.setReceiver(shoppingDetailEntity.getReceiver());insertShoppingDetail.setNum(shoppingDetailEntity.getNum());insertShoppingDetail.setCreateTime(new Date());insertShoppingDetail.setCreateBy("excel导入");shoppingDetailMapper.insert(insertShoppingDetail);} else {System.out.println("已存在记录:orderId:" + shoppingDetailEntity.getOrderId() + ", address:" + shoppingDetailEntity.getAddress() + ", goodName:" + shoppingDetailEntity.getGoodName());}}}}
}
实现导入Excel数据的代码设计方案:
1、选中sheet分页:workbook.getSheetAt(i);
2、遍历excel表格的所有行数据:for (int j = 0; j < physicalNumberOfRows; j++)
3、遍历选中行的所有列的数据:for (int k = 0; k < physicalNumberOfCells; k++)
4、通过枚举类获取excel表头对应的列属性名:ShoppingDetailEnum.get(cellValue)
5、通过反射将excel表格中的列的对应数据,设置都需要导入的对象的属性值中:
Object cellValue = ExcelUtil.getCellValue(row, k); declaredField.setAccessible(true); declaredField.set(shoppingDetailEntity, cellValue);
6、将数据对象保存到数据库中:
shoppingDetailMapper.insert(insertShoppingDetail);
PS:也可以做成批量导入,将excel中的数据全部组装完成后,添加到集合中,最后再进行批量插入
导入结果:
总结:
Excel的数据导入在实际应用场景中可能更复杂,因为在实际使用的系统可能是分布式环境,测试到不同服务间,同时导入的也可能不是一张表的数据,数据的校验规则也比较复杂,还有异常的机制设计,比如:导入重复的返回提示,数据是否需要继续插入,还是全部失败?跨服务调用的接口超时怎么设置,超时时间设置成多大可以符合实际应用场景?
需要考虑的东西太多了,就不一一赘述了,但是excel导入的核心已经全部体现在案例中了,其他的都属于实际应用中的扩展,可以根据实际业务来设计,当然实现方案还有别的方式,这里展开的就是当前的实现方式来叙述的。
JAVA实现Excel模板导入案例分析相关推荐
- Java下载excel模板
接上篇 -- "下载功能"实现 Excel模板数据导入 参考 上一篇 : Java实现Excel模板导入 正文: 一.接口层: /*** 下载** @param res respo ...
- java 分析excel模板,java 根据excel模板导出excel
java 根据excel模板导出excel 由于项目需求,最近做了一个需要根据查询接口导出excel表格数据的需求 pom依赖: org.apache.poi poi 3.16 org.apache. ...
- 【转帖】Java实现Excel批量导入数据
这篇文章主要为大家详细介绍了Java实现Excel批量导入数据,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 Excel的批量导入是很常见的功能,这里采用Jxl实现,数 ...
- VUE+JAVA实现EXCEL模板下载
一.项目场景: VUE+JAVA实现EXCEL模板下载 二.功能背景 本人作为一个开发小白,今天接到一个小需求系统需要导入数据,也就十几个字段,我和老板说了,让客户一个一个去输入吧!然后我就被经理叫去 ...
- java通过Excel 模板导出复杂统计类excel文档,在ruoyi前后端分离框架中的应用
Hello, 大家好! 我是不作死就不会死,智商不在线,但颜值超有品的拆家队大队长 --咖啡汪 一只不是在戏精,就是在戏精路上的极品二哈 前几天刚做了java通过Excel 模板导出复杂统计类exce ...
- Java实现excel模板
Java实现excel模板 Java代码 前端调用 Java代码 @ApiOperation("下载模板")@RequestMapping(value = "/model ...
- java 根据excel模板导出excel
java 根据excel模板导出excel 由于项目需求,最近做了一个需要根据查询接口导出excel表格数据的需求 pom依赖: <dependency><groupId>or ...
- java excel 导入 关闭,excel关联别的表格数据库-java实现excel表导入,有的字段数据库中没有,需要关......
excel中我想用另一张表的内容我数据库,当我在一个... 用VLOOKUP函数,=VLOOKUP(lookup_value,table_array,col_index_num,range_looku ...
- VUE+ElementUI生成Excel模板 导入数据生成表格(自适应)
VUE+ElementUI生成Excel模板 导入数据生成表格(自适应) 最近项目需求,需要根据条件查询对应数据的参数(每条数据的参数名称和个数都不一样) ,生成Excel表格模板,再通过Excel模 ...
最新文章
- 什么是智能仓储?一文带你彻底搞懂!
- leetcode处女作
- WCF布署问题1 :HTTP 错误 404.17 - Not Found 请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理。...
- android界面基本属性
- JavaScript的函数
- c 语言贪心钓鱼思路,2020届九年级中考语文复习教案:第4讲现代文阅读之概括(27页)-原创力文档...
- Jvm原理剖析与调优之内存结构
- 自媒体发展陷入僵局,社群媒体将成出路?呵呵…
- 算法模型该如何解释?
- Nginx端口占用问题
- 搭建spring MVC项目
- Jenkins 与 Kubernetes 的 CI 与 CD Git + Maven + Docker+Kubectl
- 3==num VS num==3
- iPhone开发:类似iChat的聊天泡泡
- 如何用ftp上传到服务器视频文件,ftp如何将文件上传到服务器上
- 上电瞬间电容相当于短路
- 【Tensorflow】op的理解和自定义损失函数
- 用python画熊_Python数据可视化:Pandas库,只要一行代码就能实现
- java中.level_java中的Level level是什么意思呢
- 《Excel数据可视化:一样的数据不一样的图表》——3.5用图标集让你的数据大放异彩...