需求
1、高效率的以excel表格的方式导入多条数据。
2、以身份证号为唯一标识,如果身份证号已存在,则该条数据不导入。

分析
刚开始的时候是传统的做法,解析excel数据,获取单个对象,判断身份证是否已存在表中,若没有则插入数据库。否则pass
结果数据才几百条的时候,导数据都花了10分钟才导入完毕。实在太慢了,看来在程序中做数据的校验很脑残。

优化
在插入数据库之前作判断太花时间,没必要。所以最后将数据的处理交给了数据库来做。
建一个临时表CUST_OBJECT_TEMP,先把所有的数据都用 jdbc batch insert 插入或者分数据段插入,这个过程不做任何的数据校验。
再搞个存储过程来处理两个表的数据就行了。

详细代码

①  加载上传的xls文件

  private File file; //上传的文件
  private String fileFileName; //文件名称   public File getImage() {
return image;
  }
  public void setImage(File image) {
this.image = image;
  }   public String getImageFileName() {
return imageFileName;
  }   public void setImageFileName(String imageFileName) {
this.imageFileName = imageFileName;
  } public String importExcel() throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
String realpath = ServletActionContext.getServletContext().getRealPath("/");
if (file != null) {
File savefile = new File(new File(realpath), fileFileName);
if (!savefile.getParentFile().exists()){
savefile.getParentFile().mkdirs();
}
FileUtils.copyFile(file, savefile);
String newName = savefile.getName(); //执行操作
dao.addAll(realpath+newName);
}
return SUCCESS;
}

② 解析excel并调用存储过程

public void addAll(String url){

        //生成一个备用码
String guid=RandomUtils.myGetNo(9); //将excel数据转为集合并以100条每次的节奏插入临时表中
Workbook rwb = null;
try {
//InputStream is = new FileInputStream("F:/龙里县贫困户.xls");
InputStream is = new FileInputStream(url);
rwb = Workbook.getWorkbook(is);
} catch (Exception ex) {
ex.printStackTrace();
} //获取第一张Sheet表
Sheet rs = (Sheet) rwb.getSheet(0);
//总行数
int rsRows = rs.getRows();
//总列数
int rsColumns = rs.getColumns();
Cell c1,c2 = null;
String strTmp1,strTmp2=""; int no=Integer.parseInt(findMaxId())+10;
System.out.println("总行数"+rsRows+"总列数"+rsColumns+" "+no);
try {
openConn();
//设置为不自动提交,等凑足100条的时候再批量提交一次
conn.setAutoCommit(false);
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
} catch (SQLException e1) {
e1.printStackTrace();
} for(int i=2;i<rsRows;i++){
c1 = ((jxl.Sheet) rs).getCell(0, i);
strTmp1 = c1.getContents();
c2 = ((jxl.Sheet) rs).getCell(1, i);
strTmp2 = c2.getContents(); no++; if(!strTmp1.equals("") && !strTmp3.equals("")){
StringBuilder strSql = new StringBuilder();
strSql.append(" INSERT INTO CUST_OBJECT_TEMP ");//CUST_OBJECT_TEMP
strSql.append(" (CUST_ID,CREDENTIALS,COUNZHENG,GUID) ");
strSql.append(" VALUES ");
strSql.append(" ('"+no+"','"+strTmp1+"','"+strTmp2+"','"+guid+"') "); try {
stmt.execute(strSql.toString());
//100条数据提交一次
if(i%100==0||i==(rsRows-1)){
conn.commit();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
try {
closeAll();
}catch (Exception e) {
e.printStackTrace();
} //至此所有的excel数据都已经插入到了临时表CUST_OBEJCT_YEMP中了
//注意:临时表除了有正是表的所有字段,还额外新增了两个字段
1、IF_INSERT 建表的时候默认为0 表示该数据还没有插入正式表 ,当插入正是表之后,会变为1.
2、GUID 标识了数据的批次,String guid=RandomUtils.myGetNo(9); 每一次excel导入的数据都同属于一个批次。 //调用存储过程
excelAlladd(guid);
}

③ 调用存储过程定义

public String excelAlladd(String guid){
String result = "1"; openConn();
try{
CallableStatement c=(CallableStatement) conn.prepareCall("{call PRO_CUST_TABLE(?,?)}");
c.setString(1,guid);//传入批次号guid
c.registerOutParameter(2, Types.INTEGER);//设置返回值类型为INT
c.execute(); result = c.getString(2); //获取返回值 if("0".equals(result)){
System.out.println("存储过程调用成功");
}else{
System.out.println("存储过程调用失败");
}
}catch (Exception e) {
System.out.println("调用存储过程"+e);
}
closeAll(); return result;
}

④ 存储过程定义

CREATE OR REPLACE PROCEDURE PRO_CUST_TABLE(V_GUID VARCHAR2,V_RETURN OUT integer)
IS V_CNT_1 NUMBER;//定义变量V_CNT_1
V_RETCODE VARCHAR2(20);//定义结果代码
V_RETINFO VARCHAR2(20);//定义结果提示 //开始执行存储过程
BEGIN
//取得满足A.IF_INSERT = 0 AND A.GUID = V_GUID(未插入正式表且是同一个批次号)的数据条数 作为 V_CNT_1变量的值
SELECT COUNT(*) INTO V_CNT_1 FROM CUST_OBJECT_TEMP A WHERE A.IF_INSERT = 0 AND A.GUID = V_GUID; V_RETURN := 1;//定义返回值为1 //如果有符合插入条件的数据则执行以下操作
IF V_CNT_1 > 0 THEN //1) 将满足条件的数据插入到正式表中
INSERT INTO CUST_OBJECT(
cust_id,
CREDENTIALS,
COUNZHENG
)
SELECT
CUST_ID,
CREDENTIALS,
COUNZHENG
FROM CUST_OBJECT_TEMP A1
WHERE IF_INSERT = 0
AND A1.GUID = V_GUID
AND NOT EXISTS (
SELECT 1 FROM CUST_OBJECT A2 WHERE TRIM(A1.CREDENTIALS) = TRIM(A2.CREDENTIALS)
);
COMMIT; //2) 将满足条件的数据的插入状态更新为已插入IF_INSERT = 1
UPDATE CUST_OBJECT_TEMP A SET IF_INSERT = 1 WHERE IF_INSERT = 0 AND A.GUID = V_GUID;
COMMIT; //3) 将临时表已插入状态的数据插入历史记录表 HIS_CUST_OBJECT 作为追溯的证据
INSERT INTO HIS_CUST_OBJECT(
CUST_ID,
CREDENTIALS,
COUNZHENG,
IF_INSERT
)
SELECT
CUST_ID,
CREDENTIALS,
COUNZHENG,
IF_INSERT
FROM CUST_OBJECT_TEMP A
WHERE IF_INSERT = 1 AND A.GUID = V_GUID;
COMMIT; //4) 删除临时表的数据
DELETE FROM CUST_OBJECT_TEMP A WHERE IF_INSERT = 1 AND A.GUID = V_GUID;
COMMIT; //如果这些都通过了,设置返回值为0
V_RETURN := 0;
END IF; //捕捉异常
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
V_RETCODE := 'FAIL';
V_RETINFO := SQLERRM;
end;

[Java] 高效快速导入EXCEL数据的更多相关文章

  1. java 使用poi 导入Excel 数据到数据库

    由于我个人电脑装的Excel是2016版本的,所以这地方我使用了XSSF 方式导入 . 1先手要制定一个Excel 模板 把模板放入javaWeb工程的某一个目录下如图: 2模板建好了后,先实现模板下 ...

  2. 快速导入Excel数据到mysql

    首先利用mysql文件,导出csv文件, 然后,直接修改csv文件,然后导入csv文件  

  3. Oracle导入excel数据快速方法

    Oracle导入excel数据快速方法 使用PLSQL  Developer工具,这个可是大名鼎鼎的Oracle  DBA最常使用的工具.    在单个文件不大的情况下(少于100000行),并且目的 ...

  4. springboot批量导入excel数据

    1 背景 小白今天闲着没事,在公司摸鱼,以为今天有事无聊的一天,突然上头说小子,今天实现一下批量导入Excel数据吧,当时我的内心是拒绝的,然后默默打开idea. 2 介绍 2.1 框架 java本身 ...

  5. SQL Server服务器上需要导入Excel数据的必要条件

    SQL Server服务器上需要导入Excel数据,必须安装2007 Office system 驱动程序:数据连接组件,或者Access2010的数据库引擎可再发行程序包,这样就不必在服务器上装Ex ...

  6. PLSQL Developer导入Excel数据

    LSQL Developer导入Excel数据 最近处理将Excel数据导入Oracle的工作比较多.之前都是采用Sqlldr命令行导入的方式处理.每次导入不同格式的Excel表数据,都需要先把Exc ...

  7. 导入excel数据

    前提条件:先要安装好EXCEL软件. 程序中经常要用到导入excel数据的功能.其实通过ole操作excel就简单的几行代码,但记性不好,经常要用经常要找, 还是作篇笔记吧. var ExcelApp ...

  8. (转)PLSQL Developer导入Excel数据

    场景:近来在做加班记录的统计,主要是统计Excel表格中的时间,因为我对于Excel表格的操作不是很熟悉,所以就想到把表格中的数据导入到数据库中,通过脚本语言来统计,就很方便了!但是目前来看,我还没有 ...

  9. 结合bootstrap fileinput插件和Bootstrap-table表格插件,实现文件上传、预览、提交的导入Excel数据操作流程

    1.bootstrap-fileinpu的简单介绍 在前面的随笔,我介绍了Bootstrap-table表格插件的具体项目应用过程,本篇随笔介绍另外一个Bootstrap FieInput插件的使用, ...

随机推荐

  1. SQL Server 之 与 OVER() 函数

    在SQL SERVER 2005/2008支持两种排名开窗函数和聚集开窗函数. 一. OVER() 函数 语法结构:OVER( [ PARTITION BY ... ] [ ORDER BY ... ...

  2. 从零开始编写自己的C#框架(25)——网站部署 【转】

    服务器安全部署文档 目录1.     前言.. 3 2.     部署环境.. 3 2.1         服务器环境信息.. 3 3.     磁盘阵列配置.. 4 4.     安装操作系统.. ...

  3. 专业版Unity技巧分享:使用定制资源配置文件 ScriptableObject

    http://unity3d.9tech.cn/news/2014/0116/39639.html 通常,在游戏的开发过程中,最终会建立起一些组件,通过某种形式的配置文件接收一些数据.这些可能是程序级 ...

  4. OpenJudge百炼习题解答(C++)--题4010:2011

    题: 总时间限制:  1000ms  内存限制:  65536kB 描写叙述 已知长度最大为200位的正整数n.请求出2011^n的后四位. 输入 第一行为一个正整数k,代表有k组数据,k<=2 ...

  5. vue2.x 总结

    1.独立构建vs运行时构建 在按照vue1.0的配置配置好webpack后,会出现Failed to mount component: template or render function not ...

  6. UML学习(一)-工具介绍

    这里用于学习UML的工具是StarUML,没有什么原因为什么要用它,或许仅仅是有人说好用和比较小. 首先介绍下这个工具,来张图. 1.菜单栏(最上面) 2.快捷工具栏(菜单栏下面) 3.工具项(Too ...

  7. Windows下Hadoop编程环境配置指南

    刘勇    Email: lyssym@sina.com 本博客记录作者在工作与研究中所经历的点滴,一方面给自己的工作与生活留下印记,另一方面若是能对大家有所帮助,则幸甚至哉矣! 简介 鉴于最近在研究 ...

  8. MySQL学习总结(二)数据库以及表的基本操作

    上一节中详细的介绍了关于MySQL数据库的安装过程,接下来我们就该对数据库以及表进行一些基本的操作了. 1.数据类型 MySQL数据库中提供了整数类型.浮点数类型.定点数类型.日期和时间类型.字符串类 ...

  9. js--在页面元素上(移动到或获取焦点)、鼠标离开(或失去焦点)

    1.onfocus() 和 onblur() 是一对相反的事件 但是他们只支持一部分标签 W3C关于onblur的描述:http://www.w3school.com.cn/jsref/event_o ...

  10. Hive 中的变量

    Hive的变量前面有一个命名空间,包括三个hiveconf,system,env,还有一个hivevar hiveconf的命名空间指的是hive-site.xml下面的配置变量值. system的命 ...