项目中需要动态增加和删除字段,并上传对应的数据,以下是代码记录
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框架)