Spring boot读取Excel并存入PG数据库(一)

目录

一、前言

二、项目需求

三、数据库表设计

四、代码实现和测试

五、总结


一、前言

进入9月以来,一直忙于项目,特别是临近国庆节这半个月来,被临时拉入新的项目组,需求变化莫测,项目时间很是紧迫。我最开始并非专职Java开发,本职是大数据开发,奈何公司环境如此,也时常参与Java项目开发。很久没有认真写博客了,经历了整个忙碌的夏天,特别是9月以来,笔者有感于所经手的项目收获不小,有很多值得总结和反复推敲之处,故写下这几篇系列文章,在回顾和总结时,也希望本系列文章能够对大家有所帮助。如有不当之处,敬请指正!

本文为系列文章第一篇。

二、项目需求

废话不多说,先上需求:

拿到需求清单后,仔细查看,结合团队项目会议内容,总结出第一步也是最基础最核心的一步就是将客户的Excel表格数据导入后台PG数据库指定表。结合我们的项目架构采用的是spring boot+Mybatis,其实用自己的话来说就是实现Spring boot读取Excel并存入PG数据库,此为后端需要实现的功能,需要提供给前端一个读取Excel表格的接口,并实现将数据导入数据库。

明确了后端需要干什么,那接下来就比较清晰了。

三、数据库表设计

首选在测试库中设计所需的测试表,包含表名,表字段,关联字段等等。经过和其他开发协调沟通后,确定了测试表如下:

导入数据存储表SQL代码段:

-- ----------------------------
-- Table structure for zgq_user
-- ----------------------------
DROP TABLE IF EXISTS "public"."zgq_user";
CREATE TABLE "public"."zgq_user" ("id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL DEFAULT NULL,"xm" varchar(64) COLLATE "pg_catalog"."default" DEFAULT NULL,"xb" varchar(10) COLLATE "pg_catalog"."default" DEFAULT NULL,"sfzh" varchar(32) COLLATE "pg_catalog"."default" DEFAULT NULL,"gx" varchar(32) COLLATE "pg_catalog"."default" DEFAULT NULL,"dz" varchar(64) COLLATE "pg_catalog"."default" DEFAULT NULL,"c_name" varchar(20) COLLATE "pg_catalog"."default" DEFAULT NULL,"ad_code" varchar(20) COLLATE "pg_catalog"."default" DEFAULT NULL,"ad_name" varchar(20) COLLATE "pg_catalog"."default" DEFAULT NULL,"update_by" varchar(64) COLLATE "pg_catalog"."default" DEFAULT NULL,"update_time" date DEFAULT NULL,"bz" varchar(255) COLLATE "pg_catalog"."default" DEFAULT NULL,"huhao" varchar(255) COLLATE "pg_catalog"."default" DEFAULT NULL,"bgzt" varchar(10) COLLATE "pg_catalog"."default" DEFAULT NULL
)
;
COMMENT ON COLUMN "public"."zgq_user"."id" IS '主键';
COMMENT ON COLUMN "public"."zgq_user"."xm" IS '姓名';
COMMENT ON COLUMN "public"."zgq_user"."xb" IS '性别';
COMMENT ON COLUMN "public"."zgq_user"."sfzh" IS '身份证号';
COMMENT ON COLUMN "public"."zgq_user"."gx" IS '关系';
COMMENT ON COLUMN "public"."zgq_user"."dz" IS '地址';
COMMENT ON COLUMN "public"."zgq_user"."c_name" IS '所属村';
COMMENT ON COLUMN "public"."zgq_user"."ad_code" IS '行政区划编码';
COMMENT ON COLUMN "public"."zgq_user"."ad_name" IS '行政区划名称';
COMMENT ON COLUMN "public"."zgq_user"."update_by" IS '操作人';
COMMENT ON COLUMN "public"."zgq_user"."update_time" IS '操作时间';
COMMENT ON COLUMN "public"."zgq_user"."bz" IS '备注';
COMMENT ON COLUMN "public"."zgq_user"."huhao" IS '户号';
COMMENT ON COLUMN "public"."zgq_user"."bgzt" IS '当前变更状态:默认未空';
COMMENT ON TABLE "public"."zgq_user" IS '资格权-用户记录表';-- ----------------------------
-- Primary Key structure for table zgq_user
-- ----------------------------
ALTER TABLE "public"."zgq_user" ADD CONSTRAINT "zgq_user_pkey" PRIMARY KEY ("id");

四、代码实现和测试

实现spring boot读取Excel数据并存入PG数据库,将其拆解,第一是加载或者上传Excel表格;第二读取Excel数据;第三是将数据写入PG数据表中。

本次代码其实并非完全笔者亲自写的,而且借用了同事之前写好的基础上改进的。

1、长传Excel文件接口实现

controller层:

package com.fw.hs.controller;import com.fw.hs.vo.ExcelImportVo;
import com.fw.hs.service.ExcelService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;/*** @author * @date 2020/9/8 10:09*/
@Api(tags = "excel接口")
@RestController
@AllArgsConstructor
@RequestMapping("/api/excel")
public class ExcelController {@Autowiredprivate ExcelService excelService;@ApiOperation(value = "解析excel导入数据", notes = "其他备注")@PostMapping("/import")public boolean importData(@RequestParam(name="file",required = false) MultipartFile file, ExcelImportVo vo)throws IllegalAccessException, IOException, InstantiationException {excelService.importData(file, vo.getTableName(), vo.getColumns());return true;}}

service层:

package com.fw.hs.service;import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.List;/*** @author * @date 2020/9/8 10:26*/
public interface ExcelService {void importData(MultipartFile file, String tableName, List<String> columns) throws IOException, InstantiationException, IllegalAccessException;
}

2、读取Excel表格数据

Excel工具类:

package com.fw.hs.utils;import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** @author * @date 2020/9/8 10:47*/
public class ExcelUtil {public static List<List<String>> readExcelFile(MultipartFile file, int length) throws IllegalAccessException, InstantiationException, IOException {List<List<String>> res = new ArrayList<>();String fileName = file.getOriginalFilename();Sheet sheet = null;if (StringUtils.isNotBlank(fileName)) {String suffix = fileName.substring(fileName.indexOf("."));if ("xls".equals(suffix)) {HSSFWorkbook wb = new HSSFWorkbook(file.getInputStream());sheet = wb.getSheetAt(0);} else {XSSFWorkbook wb = new XSSFWorkbook(file.getInputStream());sheet = wb.getSheetAt(0);}}if (sheet == null) {return res;}for (int j = 1;j < sheet.getPhysicalNumberOfRows();j++){List<String> list = new ArrayList<>();Row row = sheet.getRow(j);if (null != row){for (int i = 0; i < length; i++) {Cell cell = row.getCell(i);if (cell != null) {row.getCell(i).setCellType(CellType.STRING);list.add(row.getCell(i).getStringCellValue().replaceAll(" ", ""));}}}res.add(list);}return res;}
}

3、将数据写入PG数据库

service实现类:

package com.fw.hs.service.impl;import com.fw.hs.utils.ExcelUtil;
import com.fwcloud.common.base.support.IdGenerator;
import com.fw.hs.mapper.ExcelMapper;
import com.fw.hs.service.ExcelService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.List;/*** @author * @date 2020/9/8 10:26*/
@Service
@Slf4j
public class ExcelServiceImpl implements ExcelService {@Autowiredprivate ExcelMapper excelMapper;@Override@Transactional(rollbackFor = Exception.class)public void importData(MultipartFile file, String tableName, List<String> columns) throws IOException, InstantiationException, IllegalAccessException {if (CollectionUtils.isEmpty(columns)) {// 获取数据库字段名columns = excelMapper.getTableColumns(tableName);}log.info("表:{},字段:{} ", tableName, columns);List<List<String>> lists = ExcelUtil.readExcelFile(file, columns.size());for (List<String> list: lists) {if (CollectionUtils.isNotEmpty(list)) {list.add(0, String.valueOf(IdGenerator.nextId()));log.info("表:{} 导入数据:{}", tableName, list);excelMapper.insert(tableName, columns, list);}}}}

Mybatis配置:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fw.hs.mapper.ExcelMapper"><select id="getTableColumns" resultType="java.lang.String">SELECT A.attname AS NAMEFROMpg_class AS C,pg_attribute AS AWHEREC.relname = #{tableName}AND A.attrelid = C.oidAND A.attnum >0</select><insert id="insert">insert into ${tableName}<foreach item="column" index="index" collection="columns" open="(" separator="," close=")">${column}</foreach><foreach item="value" index="index" collection="values" open="values (" separator="," close=")">#{value}</foreach></insert></mapper>

4、测试

测试数据格式:

测试接口:

依次填入Excel对应的字段,一个不多,一个不少。点击选择读取文件,输入导入数据存储表zgq_user表名。然后运行后天进行测试,如图:

五、总结

由于项目紧急,需要在一周左右出一个版本,团队leader指定在原有接口基础上改,而接手时又没有任何资料或文档。虽然本次接口开发实现了基本的数据导入功能,但是考虑到具体业务和客户需求变更,总结出以下几点:

  1. 后续需求变更为所有功能从前端提供给客户,当客户点击读取Excel表格时,要让客户能明显感觉到导入数据的过程。而且客户那边要求仅仅他们所需的操作仅仅是选择所要读取的Excel文件,而本接口需要指定配置字段,存储表表名已经选择上传文件,该接口显然不符合最新的客户需求。
  2. 测试数据为3000+时,导入数据时间约为4分30秒。考虑到客户数据量有几十万条(当然了,这是最开始反馈过来的信息,数据总量为近百万条级别),所以即使是试用版本也需要解决数据导入执行过程过长导致前端响应超时问题。
  3. 在导入数据过程中实现输出数据导入日志,并按照村为单位导入。很明显,该接口是没有实现相应的需求的,也存在改进的空间,但是时间紧急,而后续的一系列需求变更导致笔者没有继续沿用同事所写接口,在此基础上改进的想法,当然也和本人的习惯有关(笔者本人不太喜欢改别人的代码,尤其是对没有文档说明,代码中注释量极少的代码很是厌恶。最起码把接口适用场景交代清楚!而leader又指定在别人接口基础修改,在没有任何资料的情况下,很是难受)。
  4. 该接口很死板,在测试时,Excel表格的字段顺序必须和测试接口swagger页面所填写的顺序一致,一旦出错就会报错。

Spring boot读取Excel并存入PG数据库(一)相关推荐

  1. python读取串口数据保存到mysql数据库_Python3读取Excel数据存入MySQL的方法

    Python是数据分析的强大利器. 利用Python做数据分析,第一步就是学习如何读取日常工作中产生各种excel报表并存入数据中,方便后续数据处理. 这里向大家分享python3如何使用xlrd读取 ...

  2. Spring Boot 操作 Excel

    Spring Boot 操作 Excel 1 新建 Spring Boot Maven 示例工程项目 2 依赖引入 Pom.xml 3 操作 Excel 3.1 创建 Workbook 3.2 创建工 ...

  3. Spring Boot——读取.properties配置文件解决方案

    解决方案 Spring Boot 读取properties配置文件时,默认读取的是application.properties. 方法一:@ConfigurationProperties注解方式 @C ...

  4. Vue + Spring Boot 学习笔记02:引入数据库实现用户登录功能

    Vue + Spring Boot 学习笔记02:引入数据库实现用户登录功能 在学习笔记01里,我们利用跨域打通了前端的Vue与后端的Spring Boot,实现了用户登录功能,但是后台的登录控制器在 ...

  5. Spring Boot读取application.yaml属性

    Spring Boot读取application.yaml属性 一.访问实体属性 1.pom.xml文件里添加snakeyaml依赖 <dependency><groupId> ...

  6. STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)

    STS创建Spring Boot项目实战(Rest接口.数据库.用户认证.分布式Token JWT.Redis操作.日志和统一异常处理) 1.项目创建 1.新建工程 2.选择打包方式,这边可以选择为打 ...

  7. python批量读取图片并批量保存_Python实现批量读取图片并存入mongodb数据库的方法示例...

    本文实例讲述了Python实现批量读取图片并存入mongodb数据库的方法.分享给大家供大家参考,具体如下: 我的图片放在E:\image\中,然后使用python将图片读取然后,显示一张,存入取一张 ...

  8. JAVA读取Excel表格,建数据库建表,并生成java实体实例

    转自:https://blog.csdn.net/wuyongde_0922/article/details/43233413 JAVA读取Excel表格,建数据库建表,并生成java实体实例,这一篇 ...

  9. spring boot读取resources下面的文件图片

    spring boot读取resources下面的文件图片 下面的代码是为了保证在打成jar包的情况下依然能够有效读取到文件. 先看项目目录结构: 我是想读取resources下面的图片,下面放上代码 ...

最新文章

  1. 贪心:remove K digits移除K个数字
  2. 如何保存PDF、Word和Excel文件到数据库中
  3. Nutch的安装和配置
  4. esp虚拟服务器,esp8266接入云服务器
  5. 拒绝无脑吹!从ACL20看预训练缺陷
  6. [转载]如何用C#语言构造蜘蛛程序
  7. php读取目录及子目录下所有文件名的方法
  8. 堆的应用之优先级队列
  9. python如何设置双索引_python-在新的多索引下串联熊猫列
  10. 系统分析师真题__专项:计算机系统与配置 2
  11. 微信小程序-005-投票功能-设置投票
  12. 360公司2019校招笔试编程题合集答案——python版本
  13. Apache Flink如何处理背压
  14. 错误:There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FAILED] certificate
  15. 如何实现转圈圈动画效果
  16. Remove WebCakeDesktop
  17. iOS截屏后仿今日头条实现一键分享
  18. 后台导出打开Excle提示:Excel无法打开文件因为文件或文件扩展名无效
  19. 深度剖析淘宝天猫搜索逻辑
  20. 用Unity制作isometric风格游戏的模型与插件精选

热门文章

  1. “量身定制CRM”——拓泰TOP CRM 打造企业DIY CRM系统
  2. 隐藏文件夹vod_cache_data解惑
  3. 健身房管理系统模块功能流程图
  4. 我做了开颅实验:从胼胝体切开术和额叶前部脑白质切断术聊一聊大分子编码说和老王谬论
  5. linux终端撤销rm -r,Linux防止“rm -rf /”误操作的方法
  6. windbg- !analyze -v 信息详解
  7. 转载 | 万字深度解析 NFT 借贷市场
  8. 好用又强大的JavaScript 框架介绍
  9. 通达信l2接口Type-C功能
  10. 数据库-乐观锁和悲观锁