SpringBoot 动态导入Excel文件到数据库

功能描述:SpringBoot+JDBC Template

要实现动态效果,就不能依赖实体类,否则一个新的Excel表导入时还要添加实体类,应直接对数据库进行操作,所以不推荐使用SpringBoot JPA ,推荐使用原生的JDBC或JDBC Template,返回的是Map,List的集合 ,除此之外,还可以用字符串拼接的方式控制SQL语句,而不是返回所有字段数据

1.在pom.xml中添加依赖,主要利用POI


	org.apache.poi
	poi
	3.11

		

	org.apache.poi
	poi-ooxml
	3.9

		

	commons-fileupload
	commons-fileupload
	1.3.1



	commons-io
	commons-io
	2.4

2.数据访问层

@Repository
public class ExcelImportRepository {
	
	@Autowired
	private JdbcTemplate jdbctemplate;
	
	/**
	 * @param tableName		要插入的表
	 * @param keys			指定插入的字段值
	 * @param values		指定插入的数据值
	 */
	//添加数据
	public void addInfo(String tableName,String keys,String values) {
		StringBuilder sql = new StringBuilder();
		sql.append("insert into ").append(tableName).append("(").append(keys).append(")").append(" values (").append(values).append(")");
		jdbctemplate.update(sql.toString());
    }
}

3.Service层

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.cgs.cqwf.store.fileDownload.SystemConfig;

@Service
@Transactional
public class ExcelImportService {
	
	//注入数据访问层
	@Autowired
	private ExcelImportRepository excelimportrepository;
	
	//获取配置文件中对应属性值
	private String getProperties;
	
	toStringUtil tsu = new toStringUtil();

	/**
	 * 
	 * @param tableName		指定Excel文件导入到哪个表
	 * @param file			Excel文件
	 * @param start			指定Excel文件导入数据的起始值,全部导入则为1
	 * @return
	 * @throws Exception
	 */
	@Transactional(rollbackFor=Exception.class)
	public boolean ExcelImport(String tableName, MultipartFile file, int start) throws Exception {
		
		boolean notNull=false;    //判断Excel文件是否有内容
		String filename=file.getOriginalFilename();
		
		if (!filename.matches("^.+\\.(?i)(xls)$") && !filename.matches("^.+\\.(?i)(xlsx)$")) {
                    throw new Exception("上传文件格式不正确");
                }
		//判断Excel文件的版本
		boolean isExcel2003=true;
	        if (filename.matches("^.+\\.(?i)(xlsx)$")) {
                    isExcel2003 = false;
                }
	    
	        InputStream is=file.getInputStream();
	        Workbook wb=null;	    
	        if (isExcel2003) {
                wb = new HSSFWorkbook(is);
                } else {
                wb = new XSSFWorkbook(is);
                }
	    
	        //获取要导入的表的字段值,因为我的属性文件里表名前都加了cqwf2
  		getProperties=SystemConfig.getProperty("cqwf2."+tableName);
  		String[] info=getProperties.split(",");
  		
  		//获取Excel文件的第一页sheet,判断是否有信息
	        Sheet sheet=wb.getSheetAt(0);
	        if(sheet!=null){
	    	    notNull=true;
	        }
	    
	        //创建两个List集合,一个保存属性文件中的字段值,一个保存Excel文件中每一行的单元格的值
	        List keysList=new ArrayList();
	        List valuesList=new ArrayList();
	    
	        //获取英文字段值
	        for(int i=0;i

SystemConfig:是我在别的包下面写的工具类,用来读取属性文件,根距属性名获取对应的属性信息

属性文件里的格式:cqwf2.表名=id(数据库中表的字段名):主键(Excel文件中的表头名),name:姓名

导入的时候注意的问题空单元格导入时,单元格类型为空和内容为空是不一样的,这里提供了三个静态常量

Row.MissingCellPolicy RETURN_NULL_AND_BLANK

/** Missing cells are returned as null, Blank cells are returned as normal */
public static final MissingCellPolicy RETURN_NULL_AND_BLANK = new MissingCellPolicy();
缺失的单元格作为null返回,空白单元格作为正常返回

Row.MissingCellPolicy RETURN_BLANK_AS_NULL

/** Missing cells are returned as null, as are blank cells */
public static final MissingCellPolicy RETURN_BLANK_AS_NULL = new MissingCellPolicy();
缺失的单元格将作为null返回,空白单元格也是如此

Row.MissingCellPolicy CREATE_NULL_AS_BLANK

/** A new, blank cell is created for missing cells. Blank cells are returned as normal */
public static final MissingCellPolicy CREATE_NULL_AS_BLANK = new MissingCellPolicy();
为丢失的单元格创建一个新的空白单元格。空白单元恢复正常。

判断内容为空时,直接调用StringUtils.isBlank(Str) 方法即可,无论有几个空字符串

getPhysicalNumberOfCells和getLastCellNum的区别:

getPhysicalNumberOfCells 是获取不为空的列个数。 
getLastCellNum 是获取最后一个不为空的列是第几个。 
因此,若是excel数据中存在空行或空列,必须用getLastRow的办法才干完全读取数据。

4. Controller层


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("excelImport")
public class ExcelImportController {
	
	@Autowired
	private ExcelImportService excelImportService;
	
	/**
	 * @param tableName		Excel文件要导入的表名
	 * @param file			Excel文件
	 * @param start			Excel文件导入内容的起始点。全导入则为1
	 * @return
	 */
	@PostMapping("import")
	public boolean addStore_Test(String tableName, @RequestParam("file") MultipartFile file,int start){
		boolean a=false;
		try {
			a=excelImportService.ExcelImport(tableName,file,start);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return a;
	}
	
}

5. 工具类

public class toStringUtil {
	/*
	 * 把List集合转化成指定格式的String类型
	 */
	public String ListToString(List list){
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < list.size(); i++) {
			sb.append(list.get(i));	
			sb.append(",");	
		}
		sb.deleteCharAt(sb.length() - 1);
		return sb.toString();
	}	
	/*
	 * 判断字符串是否为数字
	 */
	public static boolean isNumber(String str){
		for (int i = 0; i < str.length(); i++) {
			if(!Character.isDigit(str.charAt(i))){
				return false;
			}
		}
		return true;
	}
	
}

总体思路:遍历Excel文件的行,列。一个Excel文件相当于一张表,一行对应一条数据,一列对应一个字段。注意空单元格的获取和SQL语句的拼接!

你可能感兴趣的:(SpringBoot)