在读取Excel表格的需求中,有像下图的这么一种表格,它的格式工整,且表格中的列名和数据库表中的列名一一对应,如下图:
Excel表:
数据库表:
此时就需要用到下面的方法。
org.apache.poi poiRELEASE org.apache.poi poi-ooxmlRELEASE commons-io commons-io2.13.0
@Data @TableName("test") public class TestDto { @ExcelImport("id") private String id; @ExcelImport("username") private String username; @ExcelImport("password") private String password; }
创建exceIUtil包,并导入ExcelClassField、ExcelExport、ExcelImport和ExcelUtils工具类。
public interface TestMapper extends BaseMapper{ }
public interface TestService extends IService{ void add(TestDto testDto); }
public class TestServiceImpl extends ServiceImplimplements TestService { public void add(TestDto testDto) { super.save(testDto);//加入数据库中 } }
@PostMapping("/GetExcel") public Result GetExcel(@RequestParam("file") MultipartFile file) throws Exception { ListtestDtos = ExcelUtils.readMultipartFile(file, TestDto.class); for (TestDto testDto : testDtos) { testService.add(testDto); } return Result.success(testDtos, "导入成功"); }
在读取Excel表格的需求中,有一种表格它的格式固定且有规律,一张表格中有写入多张数据库表格的需求,如下图:
在上图的表格中,我们需要在数据库中写入站点配置、车道配置、枪机配置等三张表的数据,且车道配置、枪机配置表的行数随着站点配置中的车道数量的变化而变化,此时就需要用到下面的方法。
详见第一种方法。
因为需要写入多张表中,所以需要创建多个实体类。且这些属于重复性操作,所以以下我就以写入两张表作为示例。
实体类1:
@Data @TableName("tri_zd_stationinfo") public class stationinfo { @ExcelImport("站点id") private Integer id; @ExcelImport("站点名称") private String station_name; @ExcelImport("业务类型") private String business_type; @ExcelImport("站点位置") private String station_position; @ExcelImport("安装日期") private Date install_date; @ExcelImport("摄像枪品牌类型") private Integer capture_brand; @ExcelImport("车道数量") private Integer lane_count; }
实体类2:
@Data @TableName("tri_zd_laneinfo") public class laneinfo { private Integer station_id; @ExcelImport("车道号") private Integer laneid; @ExcelImport("仪表ip") private String ip; }
详见第一种方法。
Mapper接口1:
public interface ExcelStationMapper extends BaseMapper{ }
Mapper接口2:
public interface ExcelLaneMapper extends BaseMapper{ //根据你的业务需求写代码,这里有删除旧数据/重复数据的需求 @Delete("delete from tri_zd_laneinfo where station_id = #{station_id};") int delByStation_id (int station_id); }
Service接口及其实现类1:
public interface ExcelStationService extends IService{ void delByStation_id(stationinfo stationinfo); void add(stationinfo stationinfo); }
@Service public class ExcelStationImpl extends ServiceImplimplements ExcelStationService { @Autowired ExcelStationMapper excelStationMapper; public void delByStation_id(stationinfo stationinfo){ excelStationMapper.deleteById(stationinfo.getId()); } @Override public void add(stationinfo stationinfo) { super.save(stationinfo); } }
Service接口及其实现类2:
public interface ExcelLaneService extends IService{ void delByStation_id(stationinfo stationinfo); void add (laneinfo laneinfo); }
@Service public class ExcelLaneImpl extends ServiceImplimplements ExcelLaneService { @Autowired ExcelLaneMapper excelLaneMapper; public void delByStation_id(stationinfo stationinfo){ excelLaneMapper.delByStation_id(stationinfo.getId()); } @Override public void add(laneinfo laneinfo) { super.save(laneinfo); } }
//读取excel表格内容 @Autowired private ExcelStationService excelStationService; @Autowired private ExcelLaneService excelLaneService; @PostMapping("/GetExcel") public Result GetExcel(@RequestParam("file") MultipartFile file) throws Exception{ Liststationinfos = new ArrayList<>(); List laneinfos = new ArrayList<>(); try { InputStream inputStream = file.getInputStream(); Workbook workbook = new HSSFWorkbook(inputStream); // 假设 Excel 表格的第一个工作表是要读取的工作表 Sheet sheet = workbook.getSheetAt(0); stationinfo stationinfo = new stationinfo(); for (int i = 2; i<3;i++){ Row row = sheet.getRow(i); String cellValue = row.getCell(1).toString(); // 获取单元格的字符串值 int intValue; try { // 尝试将字符串转换为整数 intValue = (int) Double.parseDouble(cellValue); } catch (NumberFormatException e) { // 转换失败时的处理,赋予默认值 intValue = 0; // 默认值为0 } stationinfo.setId(intValue); stationinfo.setStation_name(row.getCell(2).toString()); stationinfo.setBusiness_type(row.getCell(3).toString()); stationinfo.setStation_position(row.getCell(4).toString()); stationinfo.setInstall_date(row.getCell(5).getDateCellValue()); String cellValue2 = row.getCell(6).toString(); // 获取单元格的字符串值 int intValue2; try { // 尝试将字符串转换为整数 intValue2 = (int) Double.parseDouble(cellValue2); } catch (NumberFormatException e) { // 转换失败时的处理,赋予默认值 intValue2 = 0; // 默认值为0 } stationinfo.setCapture_brand(intValue2); String cellValue3 = row.getCell(7).toString(); // 获取单元格的字符串值 int intValue3; try { // 尝试将字符串转换为整数 intValue3 = (int) Double.parseDouble(cellValue3); } catch (NumberFormatException e) { // 转换失败时的处理,赋予默认值 intValue3 = 0; // 默认值为0 } stationinfo.setLane_count(intValue3); stationinfos.add(stationinfo); } int y = stationinfo.getLane_count(); for (int i = 5; i < y + 5; i++){ Row row = sheet.getRow(i); laneinfo laneinfo = new laneinfo(); laneinfo.setStation_id(stationinfo.getId()); String cellValue = row.getCell(1).toString(); // 获取单元格的字符串值 int intValue; try { // 尝试将字符串转换为整数 intValue = (int) Double.parseDouble(cellValue); } catch (NumberFormatException e) { // 转换失败时的处理,赋予默认值 intValue = 0; // 默认值为0 } laneinfo.setLaneid(intValue); laneinfo.setIp(row.getCell(2).toString()); laneinfos.add(laneinfo); } //删除旧数据/重复数据 excelStationService.delByStation_id(stationinfo); System.out.println(stationinfos); for (stationinfo stationinfo1 : stationinfos){ excelStationService.add(stationinfo1); } //删除旧数据/重复数据 excelLaneService.delByStation_id(stationinfo); System.out.println(laneinfos); for (laneinfo laneinfo : laneinfos){ excelLaneService.add(laneinfo); } }catch (IOException e) { e.printStackTrace(); } return Result.success("导入成功","导入成功"); }
这个错误貌似很多人也遇到过,是SpringBoot中关于打印MultipartFile类型参数的log问题,而且大家也都没有具体的问题原因和解决方案,大多数人都是把有关的日志注解给注释掉来解决问题,虽然这种方法不能从根本上解决问题,但胜在方便,所以我也修改了项目中用AOP(面向切面编程)实现的日志处理切面的代码。
/** * 定义切面 */ @Pointcut("execution(public * com.hs.server.controller..*.*(..)) " + "&& !execution(public * com.hs.server.controller.WebApiController.DownloadLocal(..))" + "&& !execution(public * com.hs.server.controller.TriStationController.GetExcel(..))") //GetExcel接口不能应用这个切面,不然会有"MultipartFile resource [file] cannot be resolved to URL"错误
因为我的项目中有使用 Spring AOP 来实现在指定的 Controller 方法执行前和执行后进行处理的切面,且GetExcel接口不能应用这个切面,所以要添加不应用切面的接口。
/** * 定义切面 */ @Pointcut("execution(public * com.hs.server.controller..*.*(..))" + " && !execution(public * com.hs.server.controller.LoginController.postAccessToken(..))" + " && !execution(public * com.hs.server.controller.ValidateCodeController.createCode(..))" + /*" && !execution(public * com.hs.server.controller.VehicleDriverMedicalController.*(com.hs.server.dto.paramsDto.UploadFileDto))" + " && !execution(public * com.hs.server.controller.VehicleDriverMedicalController.aliPayCallback(..))" +*/ " && !execution(public * com.hs.server.controller.WebApiController.download(..))" + " && !execution(public * com.hs.server.controller.WebApiController.DownloadLocal(..))" + " && !execution(public * com.hs.server.controller.WebApiController.AddVehThjl(..))" + " && !execution(public * com.hs.server.controller.TriStationController.Upload(..))" + " && !execution(public * com.hs.server.controller.TriStationController.GetExcel(..))") //GetExcel接口不能应用这个切面,不然会有"org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile cannot be cast to com.hs.server.common.ReqParams"错误