jxl導入Excel 切割List 並使用MyBatis批量插入數據庫

需求:從Excel導入大量客戶數據。java

項目環境:Spring+SpringMVC+MyBatis。數組

技術:使用jxl實現Excel數據導入。bash

方案:上傳Excel文件,Controller層讀取每行的內容保存到對象中,存儲到List中。將保存數據的List每100個對象切割並存放到一個新的List 中的,而後使用一個大的List保存這些切割好的List組,傳遞到Service層遍歷大List,將每組List傳入的Dao層,讓MyBatis批量插入數據。app

廢話很少說,上代碼ide

Controller層

//獲取用戶上傳的文件
            Workbook workbook = Workbook.getWorkbook(file.getInputStream());
            //獲取工做簿sheet
            Sheet sheet = workbook.getSheet(0);
            //獲取總行數
            int rows = sheet.getRows();

            //獲取數據表中的數據
            List<Product> productList = new ArrayList<>();
            Cell cell;

            for (int i = 1; i < rows; i++) {
                //該對象請放在循環內部,讓GC進行回收,放在循環外面。List集合中的全部對象引用相同,保存的全部對象都是同一個引用
                Product product = new Product();
                //判斷名稱是否爲空,若是爲空結束遍歷
                if (StringUtil.isEmpty(sheet.getCell(0, i).getContents())) {
                    break;
                }

                product.setId(sheet.getCell(0, i).getContents());
                product.setContent(sheet.getCell(1, i).getContents());
                //讀取時間類型
                cell = sheet.getCell(2, i);
                if (cell.getType() == CellType.DATE) {
                    DateCell dc = (DateCell) cell;
                    Date date = dc.getDate();
                    Calendar c = Calendar.getInstance();
                    c.setTime(date);
                    //解析excel的時候會默認當前輸入的時間爲格林威治時間,須要轉爲當前時區的時間(以前8小時)
                    c.add(Calendar.HOUR, -8);
                    product.setSr_material_date(c.getTime());
                }
                //讀取時間類型
                cell = sheet.getCell(3, i);
                if (cell.getType() == CellType.DATE) {
                    DateCell dc = (DateCell) cell;
                    Date date = dc.getDate();
                    Calendar c = Calendar.getInstance();
                    c.setTime(date);
                    //解析excel的時候會默認當前輸入的時間爲格林威治時間,須要轉爲當前時區的時間(以前8小時)
                    c.add(Calendar.HOUR, -8);
                    product.setDate(c.getTime());
                }
                product.setAddress(sheet.getCell(4, i).getContents());
                product.setTel(sheet.getCell(5, i).getContents());

                //將當前對象保存的productList中
                productList.add(product);
            }
            //關閉資源
            workbook.close();

            //List切割
            List<List<Product>> dataList = new ArrayList<>();
            int listSize = productList.size();
            int toIndex = 100;
            int keyToken = 0;
            for (int i = 0; i < productList.size(); i += 100) {
                // 做用爲toIndex最後沒有100條數據則剩餘幾條newList中就裝幾條
                if (i + 100 > listSize) {
                    toIndex = listSize - i;
                }
                List<Product> newList = productList.subList(i, i + toIndex);
                dataList.add(newList);
            }
         //將切割並打包好的List集合傳遞到Service層進行處理
          productService.importFromExcel(dataList);
複製代碼

Service層

@Override
    @Transactional
    public int importFromExcel(List<List<Product>> dataList) throws Exception {
        int result = 0;
        try {
            if (dataList != null) {
                for (List<SafeRepository> list : dataList) {
                    result += productMapper.batchInsertProduct(list);
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw e;
        }
        return result;
    }

複製代碼

MyBatis 批量插入

<insert id="batchInsertProduct" parameterType="java.util.List">
        INSERT INTO t_product
        (
        id,
        content,
        date,
        address,
        tel
        )
        VALUES
        <foreach collection="list" item="pd" index="index" separator=",">
            (#{pd.id},
            #{pd.content},
            #{pd.date},
            #{pd.address},
            #{pd.tel})
        </foreach>
    </insert>
複製代碼

遇到的問題

剛開始想使用Lambda的partition進行List切割的,可是發現切割後返回的是List的父類Collection,看了下ArrayList源碼,在將Collection轉換爲List操做是使用的遍歷轉換,先轉換爲對象數組。若是我這裏要這麼實現須要將切割後獲得的Collection遍歷轉換爲對象數組,再將對象數組中的多個元素中的多個對象轉換出來,就會出現n*x的時間複雜度,並非我須要的方式。就暫時使用上述的方法進行List切割。this

ArrayList源碼spa

/**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's * iterator. * * @param c the collection whose elements are to be placed into this list * @throws NullPointerException if the specified collection is null */ public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } } 複製代碼

我寫的Lambda切割List代碼excel

List<List<Product>> dataList = new ArrayList<>();
        Collection<List<Product>> partition = partition(productList, 100);
複製代碼

技術通常般,文章中有什麼說的不對的地方,或者有更好的解決辦法,還望多指教。謝謝。code

相關文章
相關標籤/搜索