基于mybatis動(dòng)態(tài)拼接SQL實(shí)現(xiàn)批量存儲(chǔ)

最近公司有個(gè)需求就是將excel的數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù),不過(guò)數(shù)據(jù)庫(kù)有三百多張表,不同的excel存在不同的表中,如果每張表都建個(gè)實(shí)體去映射需要建三百多個(gè)實(shí)體,代碼大量重復(fù)不說(shuō),工程量太大,所以想到去動(dòng)態(tài)拼接sql,批量上傳。持久層框架選擇了強(qiáng)大的mybatis,因?yàn)閯?dòng)態(tài)拼接,不采用預(yù)編譯,變量用${}代替。
將excel文件名和對(duì)應(yīng)數(shù)據(jù)庫(kù)表名存儲(chǔ)在一張表里,每次導(dǎo)入時(shí)候先去查找相應(yīng)表名。再根據(jù)表名查找表所有的字段名(通過(guò)MetaData)。
自己建一個(gè)轉(zhuǎn)化工具類(lèi):

@Slf4j
@Component
public class GetCuloumListUtil {
    @Value("${spring.datasource.url}")
    private String datasource;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;

    public List<String> getCuloumList(String tableName) throws SQLException {

        List<String> list = null;

            Connection conn = DriverManager
                    .getConnection(datasource+"?user="+username+"&password="+password);
            DatabaseMetaData metaData = conn.getMetaData();
            ResultSet resultSet = metaData.getColumns(null, "%", tableName, "%");
            list = new ArrayList<>();
            while (resultSet.next()) {
                String columnName = resultSet.getString("COLUMN_NAME");
                list.add(columnName);
            }

        log.info(tableName+"表字段名:{}", list.toString());
        return list;
    }

}

由于動(dòng)態(tài)構(gòu)建sql不創(chuàng)建實(shí)體,所以將讀取每一列的值放到一個(gè)map中,key是列的序號(hào),value是列的值,由于要求map中值有序,所以采用TreeMap實(shí)例化。讀取的每一行是一個(gè)map,再將每一行的map放到一個(gè)list中。poi導(dǎo)入就不介紹了,這里部分代碼如下:

for(int r=1;r<totalRows;r++){
            Map<Integer,String> map=new TreeMap();//要求map有序
            Row row = sheet.getRow(r);
            if (row == null) continue;

            //循環(huán)Excel的列
            for(int c = 0; c <this.totalCells; c++){

                if(row.getCell(c)!=null&&!row.getCell(c).equals("")){
                    if (row.getCell(c).getCellType()== HSSFCell.CELL_TYPE_NUMERIC){
                        log.info("cell類(lèi)型是:{}",row.getCell(c).getCellStyle().getDataFormatString());
                        if(HSSFDateUtil.isCellDateFormatted(row.getCell(c))){//時(shí)間類(lèi)型的列
                            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            Date date = HSSFDateUtil.getJavaDate(row.getCell(c).getNumericCellValue());
                            map.put(c,dateFormat.format(date));
                        }else {
                            row.getCell(c).setCellType(Cell.CELL_TYPE_STRING);
                            map.put(c,row.getCell(c).getStringCellValue());
                        }
                    }else {
                        row.getCell(c).setCellType(Cell.CELL_TYPE_STRING);//列類(lèi)型轉(zhuǎn)為String
                        map.put(c,row.getCell(c).getStringCellValue());//列值存在map中
                    }
                }else {
                    map.put(c,"");
                }
            }
            list.add(map);
        }

mapping.xml配置文件:

<insert id="add">
    INSERT INTO ${tableName}
    <foreach collection="culoum" item="item" separator="," open="(" close=")">
        ${item}
    </foreach>
    VALUES
    <foreach collection="value" item="list" separator=",">

       <foreach collection="list.values" item="val" separator="," open="(" close=")">
         '${val}'
       </foreach>
    </foreach>
</insert>

這里采用了嵌套foreach循環(huán),里面的collection可以直接用list.values取出map的value值,如果想取出map的key值可以用list.key,這也是mybatis的強(qiáng)大之處啊。
dao層代碼:

  void add(@Param("tableName") String tableName, @Param("culoum") List culoum, @Param("value") List<Map<Integer, String>> value);

注意:
1、由于動(dòng)態(tài)sql沒(méi)有采用預(yù)編譯,所以需要我們手動(dòng)處理sql注入的問(wèn)題。
2、由于mysql默認(rèn)接受data最大是1M,也就是超過(guò)了就會(huì)失敗。所以excel文件過(guò)大時(shí)候要設(shè)置max_allow_packet。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容