【Mybatis】动态增加删除字段以及update时遍历map对象

项目中需要动态增加和删除字段,并上传对应的数据,以下是代码记录

1.动态增加、删除字段

mapper.xml

	<!--修改表结构,增加列-->
    <update id="AlterTableAddField">
        ALTER TABLE population_info ADD (${columnName} VARCHAR(255) NOT NULL DEFAULT '0')
    </update>
    
    <!--修改表结构,删除列-->
    <update id="AlterTableDeleteField">
        ALTER TABLE population_info DROP COLUMN ${columnName}
    </update>

注意这里要用$而不是#
dao层

	/**修改表结构,添加字段**/
    void AlterTableAddField(@Param("columnName") String columnName);

    /**修改表结构,删除字段**/
    void AlterTableDeleteField(@Param("columnName") String columnName);

2.上传excel

/**人口信息动态导入excel**/
    @Override
    public String InputPopulationExcel(InputStream is, String originalFilename) {
        System.out.println("service层:传入excel文件");
        Map<String,Map<String,Object>> param = new HashMap<String,Map<String,Object>>();
        Map<String,Object> ginsengMap = new HashMap<String,Object>();
        List<ArrayList<Object>> list;
        if (originalFilename.endsWith(".xls")) {
            System.out.println("service层:是2003版的excel");
            list = Excel.readExcel2003(is);
        } else {
            System.out.println("service层:是2007版的excel");
            list = Excel.readExcel2007(is);
        }
        assert list != null;
        //[id, district, lng, lat, adcode, year, population_changzhu, population_wailai, ..., 经济, 文化, 政治]
        ArrayList<Object> columnNameObjects = list.get(0);
        System.out.println(columnNameObjects.toString());
        for (int i=1;i<list.size();i++){
            List<Object> row = list.get(i);//从第一行开始,第0行是字段名
            System.out.println("service层:当前i= "+i);
            System.out.println("service层:当前row= "+row);
            for (int j = 0; j < columnNameObjects.size(); j++) {
                if(columnNameObjects.get(j).toString().equals("id")){
                    continue;
                }
                ginsengMap.put(columnNameObjects.get(j).toString(), row.get(j).toString());
            }
            param.put("keys", ginsengMap);
            populationReportDao.InputPopulationExcel(param);
            System.out.println("service层:inputExcel成功");
        }
        return "01";

上传excel的接口为populationReportDao.InputPopulationExcel(param),注意这里Map的形式为{“keys”:{“字段1”:value1;“字段2”:value2;“字段3”:value3;…}},这里采取的是按行插入的方式,也就是map里放一行数据,去sql里插入

/**人口信息导入**/
    void InputPopulationExcel(Map<String, Map<String, Object>> param);
<!--Excel导入-->
    <insert id="InputPopulationExcel" parameterType="hashmap" useGeneratedKeys="true">
        insert into population_info
        <foreach collection="keys" index="key" item="value" open="(" close=")" separator=",">
            ${key}
        </foreach>
        values
        <foreach collection="keys" item="value1" open="(" close=")" separator=",">
            #{value1}
        </foreach>

    </insert>

excel的结构如下
在这里插入图片描述

3.增加新列后更新数据表

这里先不讨论根据唯一键来更新的情况,假设现在要更新的数据的id与数据库中的id一一对应

/**上传excel,更新人口信息新增字段**/
    @Override
    public String UpdatePopulationNewColumnExcel(InputStream is, String originalFilename) {
        System.out.println("service层:传入excel文件,更新人口信息新增字段");
        List<ArrayList<Object>> list;
        if (originalFilename.endsWith(".xls")) {
            System.out.println("service层:是2003版的excel");
            list = Excel.readExcel2003(is);
        } else {
            System.out.println("service层:是2007版的excel");
            list = Excel.readExcel2007(is);
        }
        assert list != null;
        //[id, district, lng, lat, adcode, year, population_changzhu, population_wailai, ..., 经济, 文化, 政治]
        ArrayList<Object> columnNameObjects = list.get(0);//获取待更新的列名
        System.out.println(columnNameObjects.toString());

        List<String> columnNameList = new ArrayList<>();
        //这个数值可以在数据库中获取,判断上一次增加字段后总共有多少列,从新增的列开始更新数据
        for (Object columnNameObject : columnNameObjects) {
            if (columnNameObject.toString().equals("id")){
                continue;
            }
            columnNameList.add(columnNameObject.toString());//经济、技术、文化
        }

        /**
         * 按map方式遍历,按行更新
         */
        /*
        Map<String,Object> columnNewMap = new HashMap<>(); //新增字段与数据一一对应
        //遍历每一行数据,对于每一个新增字段,按行更新数值
        for (int j=1;j<list.size();j++){//对于每一行数据
            List<Object> row = list.get(j);//获取该行数据.下面截取新增字段的数据
            //对于每一个新增字段
            for (int i = 0; i < columnNameList.size(); i++) {
                String columnNew = columnNameList.get(i);//获取每一个字段名称,经济
                String value = row.get(24 + i).toString();
//                populationReportDao.updateEachValue(columnNew, value, j);//逐值更新方法,效率低
                columnNewMap.put(columnNew, value);
            }
            //每一行的值填完之后使用map更新
            Integer integer = populationReportDao.UpdatePopulationNewExcel(columnNewMap, j);
            if (integer > 0){
                System.out.println("service层:新增字段更新数据成功");
            }
        }
        */

        /**
         * 按字段更新
         */
        //遍历新增字段,对于每一个新增字段,按行更新数值
        Map<Integer, String> columnNewListMap = new HashMap<>();//每一个字段创建一个新的List
        for (int i = 0; i < columnNameList.size(); i++){//对于每一个新增字段
            String columnNew = columnNameList.get(i);//获取每一个字段名称,经济
            for (int j = 1; j < list.size(); j++) {//对于每一行数据
                List<Object> row = list.get(j);//获取该行数据.下面截取新增字段的数据
                //对于每一个新增字段
                String value = row.get(i).toString();
                columnNewListMap.put(j, value);
            }
//            for (Map.Entry<Integer, String> entry : columnNewListMap.entrySet()){
//                System.out.print(entry.getKey() + ": " + entry.getValue());
//            }
            System.out.println();
            //每一行的值填完之后使用map更新
            Integer integer = populationReportDao.UpdatePopulationNewExcelByListMap(columnNew, columnNewListMap);
            if (integer > 0){
                System.out.println("service层:新增字段更新数据成功");
            }
        }
        return "01";
    }

上面给出了两种更新的方法

①按行更新的方式

 Map<String,Object> columnNewMap = new HashMap<>(); //新增字段与数据一一对应
        //遍历每一行数据,对于每一个新增字段,按行更新数值
        for (int j=1;j<list.size();j++){//对于每一行数据
            List<Object> row = list.get(j);//获取该行数据.下面截取新增字段的数据
            //对于每一个新增字段
            for (int i = 0; i < columnNameList.size(); i++) {
                String columnNew = columnNameList.get(i);//获取每一个字段名称,经济
                String value = row.get(24 + i).toString();
//                populationReportDao.updateEachValue(columnNew, value, j);//逐值更新方法,效率低
                columnNewMap.put(columnNew, value);
            }
            //每一行的值填完之后使用map更新
            Integer integer = populationReportDao.UpdatePopulationNewExcel(columnNewMap, j);
            if (integer > 0){
                System.out.println("service层:新增字段更新数据成功");
            }
        }

UpdatePopulationNewExcel接口:

/**人口新增字段更新,按行更新**/
    Integer UpdatePopulationNewExcel(@Param("param") Map<String, Object> columnNewMap,@Param("rowId") Integer rowId);

注意这里并没有嵌套一个map

<!--上传Excel更新新增字段,按行更新-->
    <update id="UpdatePopulationNewExcel" parameterType="hashmap" useGeneratedKeys="true">
        update population_info set
        <foreach collection="param.keys" index="index" item="key" separator=",">
            ${key} = #{param[${key}]}
        </foreach>
        where id = #{rowId}
    </update>

②按列更新的方式

也就是对于每一个字段,将所有记录添加到map里再去更新

 		/**
         * 按字段更新
         */
        //遍历新增字段,对于每一个新增字段,按行更新数值
        Map<Integer, String> columnNewListMap = new HashMap<>();//每一个字段创建一个新的List
        for (int i = 0; i < columnNameList.size(); i++){//对于每一个新增字段
            String columnNew = columnNameList.get(i);//获取每一个字段名称,经济
            for (int j = 1; j < list.size(); j++) {//对于每一行数据
                List<Object> row = list.get(j);//获取该行数据.下面截取新增字段的数据
                //对于每一个新增字段
                String value = row.get(i).toString();
                columnNewListMap.put(j, value);
            }
//            for (Map.Entry<Integer, String> entry : columnNewListMap.entrySet()){
//                System.out.print(entry.getKey() + ": " + entry.getValue());
//            }
            System.out.println();
            //每一行的值填完之后使用map更新
            Integer integer = populationReportDao.UpdatePopulationNewExcelByListMap(columnNew, columnNewListMap);
            if (integer > 0){
                System.out.println("service层:新增字段更新数据成功");
            }
        }
/**人口新增字段更新,按字段更新**/
    Integer UpdatePopulationNewExcelByListMap(@Param("columnName") String columnName, @Param("columnNewListMap") Map<Integer, String> columnNewListMap);
<!--上传Excel更新新增字段,按列更新-->
    <update id="UpdatePopulationNewExcelByListMap" parameterType="hashmap">
        <foreach collection="columnNewListMap.entrySet()" index="key" item="value" separator=";">
            update population_info set ${columnName} = #{value} where id = #{key}
        </foreach>
    </update>

由于这里拼接sql后是多条语句执行,所以要在jdbc.properties文件中加上:&allowMultiQueries=true

jdbc.url=jdbc:mysql://localhost:3306/databases?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&allowMultiQueries=true

参考:

Mybatis中更新数据时遍历传入的Map对象
mybatis传入List实现批量更新
JavaWeb开发:Excel文件上传、解析、过滤,并存入数据库(基于SSM框架)


版权声明:本文为DJames23原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。