上次做项目时要求数据源改为Excel,与项目一起打包执行。查了一下数据源是否可以直接使用Excel的解决方案,虽然有提供可以连接Excel的驱动,但是以Excel直接操作数据实在是不方便,没有数据库的功能强大,因此想到了使用了内嵌式数据库,再编写一段上传Excel把数据更新到数据库的代码,即可同样达到数据源与项目打包的效果。

一、解决思路

要求:数据源为Excel,与项目一起打包

方法:使用内嵌式数据库,后台处理上传Excel数据至数据库

内嵌式数据库就是不需要像Mysql/Oracle一样安装启动服务,而是在项目中直接引用它的jar包即可,它会以文件的形式存在于数据库中。在此项目中我使用了sqlite3。

上传Excel数据至数据库这一块我使用了fileUpload和poi,前者是用于上传文件,后者用于从Excel中读取数据;数据库连接我采用了SpringJdbcTemplate。好啦,以下是详细的步骤。

二、详细步骤

1、安装内置数据库sqlite3

1)首先从官网下载,我是在Windows下开发的,虽然后续是在linux环境下运行,但是sqlite3它可以自己跨平台,所以我直接下载windows版本就好了。

2)解压,然后创建一个sqlite3类型的文件,在命令提示符中使用sqlite3 DatabaseName.db的命令即可在当前目录下创建一个sqlite3类型的数据库

3)你可以用Navicat等可视化工具连接数据库,也可以把数据库直接复制到项目中,然后在applicationContext配置文件中配置连接信息即可。我这里采用了C3P0连接池。如果是放在resources下面,URL可以像我这样写,另外sqlite3的所使用的驱动是org.sqlite.JDBC。用户名和密码可以不使用。

测试一下,可发现数据库能够正常连接

2、Excel读取数据并写入数据库

poi提供了Excel读取的了解决方案,有一点要注意的是,分为HSSF和XSSF,其中HSSF是针对的office2007之前的版本xls,而XSSF针对的是office2007以后的版本xlsx,我这里采用的是XSSF。

思路:上传文件存放至临时地点——读取Excel数据封装成List——清空数据库之前的数据——插入数据到数据库

读取Excel数据封装成List,主要思想就是遍历每个sheet,再在每个sheet中遍历行,取列值,每行封装成一个对象,每个sheet又封装成一个list,批量插入数据库,下面直接上代码。

读取Excel.java

public class UploadExcel {public static List<Ammeter> readXlsx(String path) throws Exception {List<Ammeter> list = new ArrayList<Ammeter>();InputStream is = new FileInputStream(path);XSSFWorkbook xssfWorkbook = new XSSFWorkbook(is);for (Sheet xssfSheet : xssfWorkbook) {if (xssfSheet == null) {continue;}for (int rowNum = 1; rowNum <= xssfSheet.getLastRowNum(); rowNum++) {Row xssfRow = xssfSheet.getRow(rowNum);if (xssfRow == null) {continue;}List<Ammeter> rowList = new ArrayList<Ammeter>();Ammeter ammeter = new Ammeter();int len=0;Cell cell = xssfRow.getCell(0);if (cell != null) {cell.setCellType(Cell.CELL_TYPE_STRING);}ammeter.setTabNumber(cell.getStringCellValue());cell = xssfRow.getCell(1);if (cell != null) {cell.setCellType(Cell.CELL_TYPE_STRING);}if((len=cell.getStringCellValue().length())>6){ammeter.setActivePower(cell.getStringCellValue().substring(0,6));}else{ammeter.setActivePower(cell.getStringCellValue());}cell = xssfRow.getCell(2);if (cell != null) {cell.setCellType(Cell.CELL_TYPE_STRING);}if((len=cell.getStringCellValue().length())>6){ammeter.setReactivePower(cell.getStringCellValue().substring(0,6));}else{ammeter.setReactivePower(cell.getStringCellValue());}cell = xssfRow.getCell(3);if (cell != null) {cell.setCellType(Cell.CELL_TYPE_STRING);}if((len=cell.getStringCellValue().length())>6){ammeter.setCumulativePower(cell.getStringCellValue().substring(0,6));}else{ammeter.setCumulativePower(cell.getStringCellValue());}cell = xssfRow.getCell(4);if (cell != null) {cell.setCellType(Cell.CELL_TYPE_STRING);}if((len=cell.getStringCellValue().length())>6){ammeter.setVoltage(cell.getStringCellValue().substring(0,6));}else{ammeter.setVoltage(cell.getStringCellValue());}cell = xssfRow.getCell(5);if (cell != null) {cell.setCellType(Cell.CELL_TYPE_STRING);}if((len=cell.getStringCellValue().length())>6){ammeter.setElectricity(cell.getStringCellValue().substring(0,6));}else{ammeter.setElectricity(cell.getStringCellValue());}cell = xssfRow.getCell(6);if (cell != null) {cell.setCellType(Cell.CELL_TYPE_STRING);}ammeter.setCurrentTime(cell.getStringCellValue());list.add(ammeter);}}return list;}
}

这里有几个点要注意一下:

1)我直接跟业务耦合了,但其实可以抽取出来作为一个工具类的;

2)读取的时候我直接将Excel单元格的类型强制转换为字符串类型,使用的cell.setCellType(Cell.CELL_TYPE_STRING),但是这个方法在新版的poi中的已经弃用了的,后续再看抽象出一个方法类的时候再写,现在先过;

3)Excel中使用下拉填充的数字读取出来有时会带若干小数,在这里我因为强制转换为字符类型,所以采用的subString进行截取,可以使用保留小数后再转换为字符串;如果使用我的subString的方法的话要先判断下字符串长度,避免产生index溢出的错误。

清空数据库Dao.java

 //清空数据库public void truncate(){String sql = "delete from ammeter";jdbcTemplate.execute(sql);}

这里要注意的几个点:

1)mysql中可以采用truncate table tableName进行清空数据库,但是sqlite3里是不支持这样的命令的,只能使用delete from tabeName命令,但是这个命令是不能删除自增ID的,即假如你有100条数据,虽然清空掉了,但是插入数据的ID是从101开始的;

2)在JdbcTemplate里,execute()方法可用于执行任何sql语句,但是一般用来执行DDL语句。

插入数据库Dao.java

//插入数据到数据库public void insert(List<Ammeter> ammeters){final List<Ammeter> tempAmmeter=ammeters;String sql = "insert into ammeter(tabNumber,activePower,reactivePower,cumulativePower,electricity,voltage,currentTime) values (?,?,?,?,?,?,?)";jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {@Overridepublic void setValues(PreparedStatement ps, int i) throws SQLException {String tabNumber=tempAmmeter.get(i).getTabNumber();String activePower=tempAmmeter.get(i).getActivePower();String reactivePower=tempAmmeter.get(i).getReactivePower();String cumulativePower=tempAmmeter.get(i).getCumulativePower();String electricity=tempAmmeter.get(i).getElectricity();String voltage=tempAmmeter.get(i).getVoltage();String currentTime=tempAmmeter.get(i).getCurrentTime();ps.setString(1, tabNumber);ps.setString(2, activePower);ps.setString(3, reactivePower);ps.setString(4, cumulativePower);ps.setString(5, electricity);ps.setString(6, voltage);ps.setString(7, currentTime);}@Overridepublic int getBatchSize() {return tempAmmeter.size();}});}

这里要注意的几个点:

1)采用了JdbcTemplate的批量插入方法batchUpdate(),一般来说update()方法用来执行增加、修改和删除等语句,batchUpdate()方法用来执行批处理相关的语句;这里有个疑问,虽然我使用了该批量插入方法,但是在执行5500多条数据时扔用了3-5min时间,具体原因暂未知;

2)如果是想要批量更新数据的话,可以采用临时数据库,先上传数据到临时数据库,再根据外键更新正式数据库,这样速度会快点。

3、客户端上传Excel

思路:浏览器上传Excel——存入项目的某个路径下——UploadExcel读取该路径下的Excel——执行操作

由于牵涉到前端页面,所以采用servlet和jsp;servet中用到了spring框架;上传文件的存放位置采用了相对路径,不能写死,避免了平台问题。直接上代码。

上传按钮.jsp

<form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" method="post" enctype="multipart/form-data" >请选择上传文件<input type="file" name="file"><br><input type="submit" value="上传">
</form>

处理上传Servlet.java

@Controller
public class UploadHandleServlet extends HttpServlet {@Autowiredprivate AmmeterDao ammeterDao;public void init() throws ServletException {/*** 利用init方法来调用Spring容器BeanFactory* 看看UserServlet是否能够通过Spring容器获取对象*/WebApplicationContext wc = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); //通过Web容器去得到BeanFactory对象AutowireCapableBeanFactory autowireCapableBeanFactory = wc.getAutowireCapableBeanFactory();autowireCapableBeanFactory.autowireBean(this);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");File file = new File(savePath);if(!file.exists()&&!file.isDirectory()){System.out.println(savePath+"目录不存在,需要创建");file.mkdir();}String message = "上传成功";try {DiskFileItemFactory diskfactory = new DiskFileItemFactory();//创建工厂类对象ServletFileUpload fileUpload = new ServletFileUpload(diskfactory);//使用工厂创建解析器对象if(!ServletFileUpload.isMultipartContent(request)){return;}List<FileItem> fileItems = fileUpload.parseRequest(request);for(FileItem item:fileItems) {if(item.isFormField()) {System.out.println(new String(item.getString().getBytes("ISO-8859-1"),"utf-8"));} else{item.write(new File(savePath+"\\"+"temp.xlsx"));System.out.println(message);}}} catch (FileUploadException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}List<Ammeter> temp= null;try {temp = UploadExcel.readXlsx(savePath+"\\"+"temp.xlsx");System.out.println(temp);} catch (Exception e) {e.printStackTrace();}ammeterDao.truncate();ammeterDao.insert(temp);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}

这里要注意的几个点:

1)由于Dao是使用了Spring框架用Autowired自动装配的,所以使用new是不会调用的,要想在servlet里使用自动装配,需要利用init方法来调用Spring容器BeanFactory,然后使用@Autowired自动装配;

2)使用fileupload的jar包。同时要有io

    <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><!-- https://mvnrepository.com/artifact/commons-io/commons-io --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>1.3.1</version></dependency>

3)不要把路径写死,要用相对路径; this.getServletContext().getRealPath("/WEB-INF/upload");这个路径指的是项目运行的真实路径,到时会在运行的Tomcat服务器下的webapps\ROOT\WEB-INF\upload产生文件;而且指定了文件名后覆盖,不用担心存储问题;

以上。

数据源为Excel的解决方法相关推荐

  1. Windows桌面右键新建未出现word/excel/ppt解决方法

    系统版本:windows7 office版本:2016 出现原因:安装wps等其他办公套件后卸载,发现右键不能新建word/excel/ppt 解决方法: 1.win+R 快捷键调出运行,输入rege ...

  2. Win11的两个实用技巧系列之嵌套虚拟化、无法新建Excel表格解决方法

    目录 Win11系统怎么启用嵌套虚拟化?Win11嵌套虚拟化开启方法 解决方法: Win11系统无法新建Excel表格解决方法 解决方法 Win11系统怎么启用嵌套虚拟化?Win11嵌套虚拟化开启方法 ...

  3. 引用Microsoft.Office.Interop.Excel的解决方法

    错误 14 命名空间"Microsoft.Office"中不存在类型或命名空间名称"Interop"(是缺少程序集引用吗?) 解决方法: 需要引用Microso ...

  4. sql2005导出Excel错误解决方法

    今天有个任务要导出数据库表到Excel文件,试了下直接导出数据,但是一直报错,然后从网上找了个sql语句: EXEC master..xp_cmdshell 'bcp 数据库.dbo.表 out d: ...

  5. Tableau导入shp文件会显示与数据源通信时出错解决方法

    不知道大家有没有跟我遇到同样的情况,Tableau导入shp文件会显示与数据源通信时出错,卡了好久,现在终于知道了,原来是版本不兼容,只需要下载2021.1.2及以上版本的tableau即可~

  6. 不小心卸载win10自带的word、excel等解决方法

    使用你的微软账户登录官网:https://www.office.com/ 点击我的账户 点击订阅与服务: 往下滑看到自己账户购买的产品,然后点击下载: 下载完成后进行双击运行,然后就会真正开始下载安装 ...

  7. c3p0如何配置多数据源的解决方法

    c3p0如何配置多数据源的解决方法 一.问题描述: 项目开发时,用c3p0管理数据连接.但是项目需要动态连接两个以上的数据库,如何用c3p0配置多数据源. 二.解决方法: 使用c3p0结合spring ...

  8. excel是计算机软件吗,解决win7网页提示‘请确认您的电脑是否安装了excel’软件的方法...

    win7网页提示发生错误请确认您的电脑是否安装了excel软件怎么办?有时候我们在将网页上的内容打印到Excel中时,可能会弹出来自网页的提示是"发生错误:请确认您的电脑是否安装了excel ...

  9. Windows桌面右键新建未出现word/excel/ppt解决办法

    系统版本:win10 office版本:office2016 出现原因:安装极速PDF阅读器其他办公套件,后卸载,发现右键不能新建word/excel/ppt 解决方法: 1.win+R快捷键调出运行 ...

最新文章

  1. Mysql DBA 高级运维学习之路-mysql数据库入门知识
  2. C/C++中的连续赋值
  3. 自由职业者在合作之前要弄懂的15个问题
  4. Python 使用穷举法求两个数的最大公约数。
  5. [Xcode 实际操作]七、文件与数据-(17)解析JSON文档
  6. 15个带示例的jQuery滚动条插件
  7. oracle批处理还原数据库,用批处理写的:数据库备份还原工具(修正加强版)
  8. js中substr与substring的区别
  9. MVC模式利用xib文件定制collectionCell
  10. linux下获取微秒级精度的时间【转】
  11. 一篇关于蓝牙SDP和L2CAP协议的文章
  12. 非常哇塞的 SpringBoot性能优化长文!
  13. 台达变频器s1参数设置_台达变频器的参数设定步骤
  14. 为什么有的python内置函数怎么就一个pass?
  15. bootstrap-table的refresh查询
  16. 本科毕业四年时间如何从月薪7k到年薪60w,讲下个人从菜鸟程序员到公司核心开发工程师的历程!
  17. 论文介绍 -- Rethinking the Evaluation of Video Summaries
  18. 批量(清除)删除Word回车符
  19. 彩色matlab代码拷贝到word研究,matlab编辑器合并_彩色MATLAB代码拷贝到WORD研究
  20. 以太坊BIP39助记词到公钥地址的原理与细节

热门文章

  1. 网络推广新手必看!如何以数据手法定义文章标题
  2. 2022-2028年全球植入前基因检测收入年复合增长率CAGR为 5.6%
  3. 软件质量测试:Jmeter察看结果树的响应数据中的中文显示乱码问题处理
  4. 57q/5oCn5Luj5pWw5Y+K5YW25bqU55So56ysNeeJiOS4reaWh1BERui1hOa6kA==
  5. 新站如何用指数蛙快速提升百度权重的方法!
  6. 用事实说话,成熟的ORM性能不是瓶颈,灵活性不是问题:EF5.0、PDF.NET5.0、Dapper原理分析与测试手记...
  7. 【精选模板】古风汉服影楼摄影PSD源文件,绝美的素材,附带预览图
  8. WAR3改键工具FinalKey beta 1.0制作完成
  9. 台湾评论大陆量子计算机,台湾媒体盛赞大陆工业科研水平 称台湾人对大陆懵懂无知...
  10. 解决maven工程的properties文件内容呈灰色