zoukankan      html  css  js  c++  java
  • 上传文件数据到数据库

    实验采用Mybatis+POI+JSON 完成解析Excel数据,并将数据批量插入数据库。

    1.POI+JSON 提取Excel中数据,同时映射实体类。

     /**
         *
         * @param   is  输入流
         * @return  输入流创建XSSFWorkBook对象
         */
         public  XSSFWorkbook XSSFReadFile(InputStream is) {
    
             XSSFWorkbook wb=null;
             try {
                 wb=new XSSFWorkbook(is);
             } catch (IOException e) {
                 e.printStackTrace();
             }
              return wb;
         }
    
    
        /**
         * @param wb XSSFWorkBook对象
         * @return 读取文件的sheet名与首行Title组装为json对象
         */
        public  JSONObject getTable(XSSFWorkbook wb){
    
            JSONObject obj=new JSONObject();
    
            JSONArray array=new JSONArray();
    
            int SheetSum = wb.getNumberOfSheets();
    
            for(int i=0;i<SheetSum;i++){
    
                 String sheetName=wb.getSheetName(i);
    
                 XSSFSheet sheet = wb.getSheetAt(i);
    
                XSSFRow row = sheet.getRow(0);
    
                if(row!=null) {
    
                    int cellsSum = row.getPhysicalNumberOfCells();
                    array.clear();
                    for (int j = 0; j < cellsSum; j++) {
    
                        array.add(row.getCell(j).getStringCellValue().trim());
                    }
                    obj.put(sheetName,array);
                }
            }
    
           return obj;
        }
         /**
          * @param   poi 类对象
          * @return  获取sheet页的全部数据
          */
    
        public  JSONArray getTableData(POIHelper poi){
    
            JSONObject table = getTable(poi.getWb());
    
            JSONArray array = JSONArray.fromObject(table.get(poi.getSheetName()));
    
            JSONArray arr=new JSONArray();
    
            JSONObject obj_sun =new JSONObject();
    
            for(int i=1;i<poi.getRowSum();i++){
    
                XSSFSheet sheet = poi.getSheet();
                XSSFRow row = sheet.getRow(i);
                obj_sun.clear();
                for(int j=0;j<poi.getCellSum();j++){
    
                    XSSFCell cell = row.getCell(j);
                    //设置单元格类型
                    cell.setCellType(CellType.STRING);
                    obj_sun.put(array.get(j),cell.getStringCellValue().trim());
                }
                arr.add(obj_sun);
            }
            return arr;
        }
    

     将一张表的数据,每行数据读成一个JSON对象放入JSONArray中,类似下面的形式:

     [{"id":"1","userName":"东邪","passWord":"123","gender":"男"},{"id":"2","userName":"西毒","passWord":"124","gender":"男"}]

     JSONArray的好处是可以将其转化为映射类的List:

    List user = JSONArray.toCollection(JSONArray对象, 映射类Class对象);

     在映射类时,Excel sheet页和首行Title习惯上都会是汉字,而数据库和数据传输都是英语,中间存在一种映射,类似于国际化的转换。

     Sheet页名与实体类名存在映射关系,sheet中首行字段转化 为英语后与实体类的属性存在映射。

     在将JSONArray转化为List<类>时,需要根据sheet页名获取实体类名,通过Class.forName(固定实体类包名+类名)

        public Class<?> getClazz(String entityName){
            Class<?> clazz=null;
            try {
                clazz =Class.forName("com.soft.entity." + entityName);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return clazz;
        }
    

    在service中进行批量插入时,调用DAO中方法,因为许多张表进行批量插入,所以不可避免地进行了硬编码

    根据sheet名,选择不同的Dao接口批处理方法。另外有一个不好的地方,如果有十张表,但是只更新了两张表,依然会将十张表插入数据库。在后续进行扩展时,添加实体类时,同时需要修改业务部分的if条件判断,

    是一个问题。写了两个类,User和product。

    public void BatchInsertData(MultipartFile file){
            try {
                XSSFWorkbook wb = poiHelper.XSSFReadFile(file.getInputStream());
                JSONObject table = poiHelper.getTable(wb);
                Set<String> set = table.keySet();
                for (String sheetName:set) {
                    POIHelper poi=new POIHelper(wb,sheetName);
                    JSONArray tableData = poi.getTableData(poi);
                    Class<?> clazz = entitymapper.getClazz(sheetName);
                    List list =(List) JSONArray.toCollection(tableData,clazz);
                    if(sheetName.equals("User")){
                        userDao.batchInsert(list);
                    }else if(sheetName.equals("Product")){
                        productDao.batchInsert(list);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    

    在最后献上mybatis,批量插入的经典SQL语句:ignore 可以避免多次重复插入相同数据时的冲突,相同时不进行插入。

     <insert id="batchInsert" parameterType="java.util.List">
    
         insert ignore into product(id,productName,price,description)
                 VALUES
                     <foreach collection="list" item="item" index="index" separator=",">
                         (
                          #{item.id},#{item.productName},#{item.price},#{item.description}
                         )
                     </foreach>
     </insert>  

    异常点:

              在页面进行上传Excel时出现   exception is org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.soft.dao.UserDao.batchInsert。

             检查mapper.xml后发现,mapper的namespace写的是实体类路径,应该是其对应DAO接口路径。修改后,问题排除。

             另外,注意在maven项目中,mapper.xml 放置在resources下,不能放在java路径下。放错位置,也会导致上面找不到接口方法的问题。

    需要完善点:

                    文件数据上传数据库前,文件格式、Sheet页、首行字段、数据等校验.

                  上文提到的硬编码问题

  • 相关阅读:
    关于spring security的若干事情
    .net2005 datagridview 如何获取值改变的单元格的集合??(小弟没有为datagridview添加数据源,也就是说单元格中的数据是手工录入的)
    关于做一个通用打印类的设想,大家谈谈看法
    请教C#,两个类中的变量互访问题
    刚发现了一个问题,关于vs2005 datagridview的,我发现在设计行标头的HeaderCell.Value的时候要是设置RowTemplate.Height 的值>= 17则行标头的那个黑三角就显示出来了,要是小于17就不能显示了,想问问大家,是怎么回事?
    软件架构模式基本概念及三者区别
    以英雄联盟的方式建模,谈对依赖注入(DI)的理解以及Autofac的用法(一)
    适配器模式
    [翻译] WCF运行时架构
    关于synchronized 影响可见性的问题
  • 原文地址:https://www.cnblogs.com/CaesarLinsa/p/8016101.html
Copyright © 2011-2022 走看看