• Java&Excel:自动生成数据表并插入数据


    故事背景

    出于好奇,当下扫描excel读取数据进数据库 or 导出数据库数据组成excel的功能层出不穷,代码也是前篇一律,poi或者easy excel两种SDK的二次利用带来了各种封装方法。

    那么为何不能直接扫描excel后根据列的属性名与行数据的属性建立SQL数据表,并将数据插入到数据表中,再通过前端与用户交互进行SQL组装,得到用户想要的数据结果。

    模块架构图

    采取原始的数据库信息读取,配置编程式事务(代码块维度锁事务),封装原始的JDBC执行模板。

    excel读取列属性名,转换成英文作为表的属性名,行解析器解析数据行数据属性作为表属性的数据类型。

    代码构成

    基础实体:

    ColumnEntity.java
    1. @Data
    2. @EqualsAndHashCode
    3. public class ColumnEntity {
    4. private String columnName;
    5. private String columnSqlInfo;
    6. public void clear(){
    7. setColumnName(null);
    8. setColumnSqlInfo(null);
    9. }
    10. }
    ValueEntity.java
    1. @Data
    2. public class ValueEntity{
    3. private String columnName;
    4. /*数据拼接到SQL上也是字符串类型*/
    5. private String valueOfString;
    6. public void clear(){
    7. setColumnName(null);
    8. setValueOfString(null);
    9. }
    10. }
    JsonResponse.java
    1. @Data
    2. @AllArgsConstructor
    3. @NoArgsConstructor
    4. public class JsonResponse {
    5. private int code = -1;
    6. private String message;
    7. private String json;
    8. public static JsonResponse success(String json){
    9. JsonResponse jsonResponse = new JsonResponse();
    10. jsonResponse.setCode(0);
    11. jsonResponse.setJson(json);
    12. jsonResponse.setMessage("访问成功");
    13. return jsonResponse;
    14. }
    15. public static JsonResponse fail(String massage){
    16. JsonResponse jsonResponse = new JsonResponse();
    17. jsonResponse.setMessage(massage);
    18. return jsonResponse;
    19. }
    20. }

    api对前端提供特性:

    WebMvcConfiguration.java
    1. @Configuration
    2. @Slf4j
    3. public class WebMvcConfiguration implements WebMvcConfigurer , HandlerInterceptor {
    4. @Override
    5. public void addInterceptors(@NonNull InterceptorRegistry registry) {
    6. registry.addInterceptor(this);
    7. WebMvcConfigurer.super.addInterceptors(registry);
    8. }
    9. @Override
    10. public void addCorsMappings(@NonNull CorsRegistry registry) {
    11. WebMvcConfigurer.super.addCorsMappings(registry);
    12. }
    13. @Override
    14. public void postHandle(@NonNull HttpServletRequest request,@NonNull HttpServletResponse response,@NonNull Object handler, ModelAndView modelAndView) throws Exception {
    15. HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    16. }
    17. @Override
    18. public boolean preHandle(HttpServletRequest request,@NonNull HttpServletResponse response,@NonNull Object handler) throws Exception {
    19. String sql = request.getParameter("sql");
    20. String tableName = request.getParameter("tableName");
    21. if (StringUtils.isNotEmpty(sql)){
    22. if (!sql.contains("test") || !tableName.contains("test")){
    23. log.error("过滤非法请求:{}",sql);
    24. return false;
    25. }
    26. if (sql.contains("DELETE") || sql.contains("delete") || sql.contains("UPDATE") || sql.contains("update")){
    27. log.error("过滤非法请求:{}",sql);
    28. return false;
    29. }
    30. }
    31. return HandlerInterceptor.super.preHandle(request, response, handler);
    32. }
    33. @Override
    34. public void afterCompletion(@NonNull HttpServletRequest request,@NonNull HttpServletResponse response,@NonNull Object handler, Exception ex) throws Exception {
    35. HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    36. }
    37. }
    ExcelDataController.java
    1. @RestController
    2. @RequestMapping("/data")
    3. @CrossOrigin
    4. @Slf4j
    5. public class ExcelDataController {
    6. @Resource
    7. private SqlDataProvider sqlDataProvider;
    8. @GetMapping("/handle/sql")
    9. @ResponseBody
    10. public JsonResponse handleData(@RequestParam String sql) {
    11. String executed = sqlDataProvider.executeQuerySql(sql);
    12. return Objects.equals("", executed)
    13. ? JsonResponse.fail("sql执行错误")
    14. : JsonResponse.success(executed);
    15. }
    16. }
    ExcelResolveController.java
    
    1. @RestController
    2. @RequestMapping("/excel")
    3. @CrossOrigin
    4. @Slf4j
    5. public class ExcelResolveController {
    6. @Resource
    7. private ExcelEntityService excelEntityService;
    8. @RequestMapping("/createAndInsert")
    9. @ResponseBody
    10. public void uploadExcel(@RequestParam("fileName") MultipartFile file) {
    11. excelEntityService.createTable(file);
    12. excelEntityService.insertEntity(file);
    13. }
    14. @RequestMapping("/insert")
    15. @ResponseBody
    16. public void insertExcel(@RequestParam("fileName") MultipartFile file) {
    17. excelEntityService.insertEntity(file);
    18. }
    19. @RequestMapping("/drop")
    20. @ResponseBody
    21. public void delData(@RequestParam("fileName")String fileName){
    22. excelEntityService.dropTable(fileName);
    23. }
    24. }
    ExcelEntityService.java
    1. public interface ExcelEntityService {
    2. /**
    3. * 创建数据表
    4. *
    5. * @param file 文件
    6. */
    7. void createTable(MultipartFile file);
    8. /**
    9. * 插入数据实体
    10. *
    11. * @param file 文件
    12. */
    13. void insertEntity(MultipartFile file);
    14. /**
    15. * 删除数据表
    16. * @param fileName 文件名
    17. */
    18. void dropTable(String fileName);
    19. }
    ExcelEntityServiceImpl.java
    1. @Service
    2. @Slf4j
    3. @ConditionalOnBean({SqlDataProvider.class,SqlSpliceProvider.class})
    4. public class ExcelEntityServiceImpl implements ExcelEntityService {
    5. @Resource
    6. private SqlDataProvider sqlDataProvider;
    7. @Resource
    8. private SqlSpliceProvider spliceProvider;
    9. @Resource
    10. private ReadExcelService readExcelService;
    11. @Override
    12. public void createTable(MultipartFile file) {
    13. String dropTableSql = spliceProvider.dropTableSql(file.getName());
    14. log.info("删表SQL:{}",dropTableSql);
    15. sqlDataProvider.executeSql(dropTableSql);
    16. List excelColumnList = readExcelService.getExcelColumnList(file);
    17. StringBuffer stringBuffer = spliceProvider.spliceCreateTableSql(excelColumnList, file.getName());
    18. log.warn("建表SQL:{}", stringBuffer);
    19. sqlDataProvider.executeSql(stringBuffer.toString());
    20. }
    21. @Override
    22. public void insertEntity(MultipartFile file) {
    23. String existsTableSql = spliceProvider.existsTableSql(file.getName());
    24. Object aReturn = sqlDataProvider.executeSqlAndGetReturn(existsTableSql);
    25. if (Objects.nonNull(aReturn)) {
    26. List excelColumnList = readExcelService.getExcelColumnList(file);
    27. Map> excelRowDataMap = readExcelService.getExcelRowDataMap(file, excelColumnList);
    28. List stringBuffer1 = spliceProvider.spliceInsertValueSql(excelRowDataMap, file.getName());
    29. stringBuffer1.forEach(s -> sqlDataProvider.executeSql(s));
    30. }else{
    31. log.warn("不存在数据表:{}",file.getName());
    32. }
    33. }
    34. @Override
    35. public void dropTable(String fileName) {
    36. String dropTableSql = spliceProvider.dropTableSql(fileName);
    37. log.info("删表SQL:{}",dropTableSql);
    38. sqlDataProvider.executeSql(dropTableSql);
    39. }
    40. }

     excel解析器:

    ReadExcelService.java
    1. public interface ReadExcelService {
    2. /**
    3. * 读取EXCEL的列属性列表
    4. *
    5. * @param file 文件
    6. * @return 列属性实体列表(只含有列的属性)
    7. */
    8. List getExcelColumnList(MultipartFile file);
    9. /**
    10. * 读取每一行的行实体列表,一个LIST为一行
    11. *
    12. * @param file 文件
    13. * @param columnEntityList 列实体列表
    14. * @return 全部的值MAP<行号 , 行的属性值LIST>
    15. */
    16. Map> getExcelRowDataMap(MultipartFile file, List columnEntityList);
    17. }
    ReadExcel.java
    1. @Slf4j
    2. @Service
    3. public class ReadExcel implements ReadExcelService {
    4. private static final Integer LIMIT_SCAN_NUM = 500 * 1000;
    5. /**
    6. * 根据文件名读取Excel文件获取列信息列表
    7. *
    8. * @param file 文件
    9. * @return List<列实体>
    10. */
    11. @Override
    12. public List getExcelColumnList(MultipartFile file) {
    13. List list;
    14. Workbook workbook = getWorkbook(file);
    15. if (Objects.isNull(workbook)) {
    16. return new LinkedList<>();
    17. }
    18. list = getExcelColumnList(workbook);
    19. return list;
    20. }
    21. /**
    22. * 获取行数与对应行得值SQL实体列表
    23. *
    24. * @param file 工作薄文件
    25. * @param columnEntityList 列信息对象
    26. * @return map<行号 , 行内每一个单元格得值SQL实体列表>
    27. */
    28. @Override
    29. public Map> getExcelRowDataMap(MultipartFile file, List columnEntityList) {
    30. Workbook workbook = getWorkbook(file);
    31. if (Objects.isNull(workbook)) {
    32. return new HashMap<>();
    33. }
    34. Sheet sheet = workbook.getSheetAt(0);
    35. int lastRowNum = sheet.getLastRowNum();
    36. Map> map = new HashMap<>();
    37. if (lastRowNum <= LIMIT_SCAN_NUM) {
    38. for (int i = 1; i <= lastRowNum; i++) {
    39. Row row = sheet.getRow(i);
    40. List list = new LinkedList<>();
    41. for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
    42. ValueEntity valueEntity = new ValueEntity();
    43. valueEntity.setColumnName(columnEntityList.get(j).getColumnName());
    44. valueEntity.setValueOfString(ExcelReadStringUtil.getValueSqlString(row.getCell(j)));
    45. list.add(valueEntity);
    46. }
    47. map.put(i, list);
    48. }
    49. }else{
    50. throw new RuntimeException("扫描的Excel文件数据量超过限定值,请检查核定容量");
    51. }
    52. return map;
    53. }
    54. /**
    55. * 解析返回excel数据表第一行属性信息列表数据
    56. *
    57. * @param workbook 数据工作薄
    58. * @return List<列实体>
    59. */
    60. private static List getExcelColumnList(Workbook workbook) {
    61. /*默认取第一个工作表的第一行数据与第二行数据(第一行用来感知属性名称、第二行用来感知属性类型)*/
    62. Sheet dataSheet = workbook.getSheetAt(0);
    63. Row topRow = dataSheet.getRow(0);
    64. Row typeRow = dataSheet.getRow(1);
    65. if (topRow.getPhysicalNumberOfCells() != typeRow.getPhysicalNumberOfCells()) {
    66. log.error("数据表列行与数据行列数不一致!退出解析,请整理数据表格式!");
    67. throw new RuntimeException("DataSheet is error: com.runjing.resolve_excel_auto.excel.ReadExcel.getExcelColumnList(org.apache.poi.ss.usermodel.Workbook)");
    68. }
    69. List columnEntityList = new LinkedList<>();
    70. for (int i = 0; i < topRow.getPhysicalNumberOfCells(); i++) {
    71. ColumnEntity columnEntity = new ColumnEntity();
    72. Cell nameCell = topRow.getCell(i);
    73. Cell typeRowCell = typeRow.getCell(i);
    74. columnEntity.setColumnName(ExcelReadStringUtil.transferPinYin(nameCell.getStringCellValue()));
    75. columnEntity.setColumnSqlInfo(ExcelReadStringUtil.switchCellDataSqlInfo(typeRowCell));
    76. columnEntityList.add(columnEntity);
    77. }
    78. return columnEntityList;
    79. }
    80. /**
    81. * 文件转换工作簿对象
    82. *
    83. * @param file excel文件
    84. * @return 工作簿对象
    85. */
    86. private static Workbook getWorkbook(MultipartFile file) {
    87. InputStream is = null;
    88. try {
    89. is = file.getInputStream();
    90. Workbook workbook;
    91. workbook = WorkbookFactory.create(is);
    92. return workbook;
    93. } catch (Exception ex) {
    94. ex.printStackTrace();
    95. return null;
    96. } finally {
    97. if (is != null) {
    98. try {
    99. is.close();
    100. } catch (IOException e) {
    101. e.printStackTrace();
    102. }
    103. }
    104. }
    105. }
    106. }

    SQL拼接器:

    ExcelReadStringUtil.java
    1. public class ExcelReadStringUtil {
    2. /*获取构建表格数据属性SQL*/
    3. public static String switchCellDataSqlInfo(Cell dataCell) {
    4. return switch (dataCell.getCellType()) {
    5. case NUMERIC -> " double default 0.00 ";
    6. case STRING -> " varchar(100) default null";
    7. case FORMULA -> " varchar default null";
    8. case BOOLEAN -> " tinyint(1) default 0";
    9. default -> " varchar(64) default null";
    10. } + ",";
    11. }
    12. /*获取单元格值SQL*/
    13. public static String getValueSqlString(Cell dataCell) {
    14. return switch (dataCell.getCellType()) {
    15. case NUMERIC -> String.valueOf(dataCell.getNumericCellValue());
    16. case STRING -> quotesHandle(dataCell.getStringCellValue());
    17. case FORMULA -> quotesHandle(dataCell.getCellFormula());
    18. case BOOLEAN -> transferBool(dataCell.getBooleanCellValue());
    19. default -> "null";
    20. };
    21. }
    22. /**
    23. * 单引号包裹字段
    24. *
    25. * @param fieldValue 字段值
    26. * @return 包裹后字段串
    27. */
    28. public static String quotesHandle(String fieldValue) {
    29. return "'" + fieldValue + "'";
    30. }
    31. /**
    32. * 布尔类型转换
    33. *
    34. * @param arg1 入参
    35. * @return 转换值
    36. */
    37. public static String transferBool(Boolean arg1) {
    38. return arg1 ? "0" : "1";
    39. }
    40. /**
    41. * 将汉字串转成拼音串
    42. *
    43. * @param columnChineseName 汉字字段名
    44. * @return 字段拼音
    45. */
    46. public static String transferPinYin(String columnChineseName) {
    47. /*转换中文为简体拼音*/
    48. return LanguageUtil.convertChineseLan2PinYinAbbreviation(columnChineseName, LanguageUtil.CHINESE_CHAR_REG_SIMPLIFIED);
    49. }
    50. }
    SqlSpliceStringUtil.java
    1. public class SqlSpliceStringUtil {
    2. /**
    3. * 反引号处理
    4. *
    5. * @param fieldName 字段名称
    6. * @return 被反引号包裹得字段名称
    7. */
    8. public static String quotesHandle(String fieldName) {
    9. return "`" + fieldName + "`";
    10. }
    11. /**
    12. * 将汉字串转成拼音串
    13. *
    14. * @param columnChineseName 汉字字段名
    15. * @return 字段拼音
    16. */
    17. public static String transferPinYin(String columnChineseName) {
    18. /*转换中文为简体拼音*/
    19. return LanguageUtil.convertChineseLan2PinYinAbbreviation(columnChineseName, LanguageUtil.CHINESE_CHAR_REG_SIMPLIFIED);
    20. }
    21. }
    LanguageUtil.java
    1. @Slf4j
    2. public class LanguageUtil {
    3. /**
    4. * 定义输出格式
    5. */
    6. public static HanyuPinyinOutputFormat hpFormat = new HanyuPinyinOutputFormat();
    7. /**
    8. * 匹配所有东亚区的语言
    9. */
    10. public static String CHINESE_CHAR_REG_SOUTHEAST_ASIA ="^[\u2E80-\u9FFF]+$";
    11. /**
    12. * 匹配简体和繁体
    13. */
    14. public static String CHINESE_CHAR_REG_SIMPLIFIED_OR_TRADITIONAL ="^[\u4E00-\u9FFF]+$";
    15. /**
    16. * 匹配简体
    17. */
    18. public static String CHINESE_CHAR_REG_SIMPLIFIED ="[\u4E00-\u9FA5]+$";
    19. static{
    20. // 大写格式输出
    21. hpFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
    22. // 不需要语调输出
    23. hpFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
    24. }
    25. /***
    26. * 将汉字转成拼音(取首字母或全拼)
    27. * @param singleChar 中文字符
    28. * @param full 是否全拼
    29. * @return 转换后拼音
    30. */
    31. public static String convertChineseChar2Pinyin(String singleChar, boolean full,String regExp ) {
    32. StringBuffer sb = new StringBuffer();
    33. if (singleChar == null || "".equals(singleChar.trim())) {
    34. return "";
    35. }
    36. String pinyin = "";
    37. for (int i = 0; i < singleChar.length(); i++) {
    38. char unit = singleChar.charAt(i);
    39. //是汉字,则转拼音
    40. if (match(String.valueOf(unit), regExp))
    41. {
    42. pinyin = convertSingleChineseChar2Pinyin(unit);
    43. if (full) {
    44. sb.append(pinyin);
    45. } else {
    46. sb.append(pinyin.charAt(0));
    47. }
    48. } else {
    49. sb.append(unit);
    50. }
    51. }
    52. return sb.toString();
    53. }
    54. /***
    55. * 将单个汉字转成拼音
    56. * @param singleChar 中文汉字
    57. * @return 拼音
    58. */
    59. private static String convertSingleChineseChar2Pinyin(char singleChar) {
    60. String[] res;
    61. StringBuffer sb = new StringBuffer();
    62. try {
    63. res = PinyinHelper.toHanyuPinyinStringArray(singleChar, hpFormat);
    64. //对于多音字,只用第一个拼音
    65. sb.append(res[0]);
    66. } catch (Exception e) {
    67. log.error("单个汉字转换成字符失败:{}",e.getMessage());
    68. return "";
    69. }
    70. return sb.toString();
    71. }
    72. /***
    73. * @param str 源字符串
    74. * @param regex 正则表达式
    75. * @return 是否匹配
    76. */
    77. public static boolean match(String str, String regex) {
    78. Pattern pattern = Pattern.compile(regex);
    79. Matcher matcher = pattern.matcher(str);
    80. return matcher.find();
    81. }
    82. /**
    83. * 汉字字符串的的首拼拼成字符串
    84. * @param chineseLan 中文字符串
    85. * @return 拼音字符串
    86. */
    87. public static String convertChineseLan2PinYinAbbreviation(String chineseLan,String regExp) {
    88. String ret = "";
    89. // 将汉字转换为字符数组
    90. char[] charChineseLan = chineseLan.toCharArray();
    91. try {
    92. for (int i = 0; i < charChineseLan.length; i++) {
    93. if(String.valueOf(charChineseLan[i]).matches(regExp)) {
    94. // 如果字符是中文,则将中文转为汉语拼音(获取全拼则去掉红色的代码即可)
    95. ret += PinyinHelper.toHanyuPinyinStringArray(charChineseLan[i], hpFormat)[0].substring(0, 1);
    96. } else {
    97. // 如果字符不是中文,则不转换
    98. ret += charChineseLan[i];
    99. }
    100. }
    101. } catch (BadHanyuPinyinOutputFormatCombination e) {
    102. log.error("获取汉字的的首拼失败:{}",e.getMessage());
    103. }
    104. return ret;
    105. }
    106. /**
    107. * 判断字符串中是否包含中文汉字
    108. *
    109. * @param content 字符串内容
    110. * @return true至少包含1个
    111. */
    112. public static boolean hasChinese(CharSequence content) {
    113. if (null == content) {
    114. return false;
    115. }
    116. String regex = "[\u2E80-\u2EFF\u2F00-\u2FDF\u31C0-\u31EF\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF\uD840\uDC00-\uD869\uDEDF\uD869\uDF00-\uD86D\uDF3F\uD86D\uDF40-\uD86E\uDC1F\uD86E\uDC20-\uD873\uDEAF\uD87E\uDC00-\uD87E\uDE1F]+";
    117. Pattern pattern = Pattern.compile(regex);
    118. return pattern.matcher(content).find();
    119. }
    120. /**
    121. * 判断字符串是否为中文汉字
    122. *
    123. * @param content 字符串内容
    124. * @return true都是汉字
    125. */
    126. public static boolean isChinese(CharSequence content) {
    127. if (null == content) {
    128. return false;
    129. }
    130. String regex = "[\u2E80-\u2EFF\u2F00-\u2FDF\u31C0-\u31EF\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF\uD840\uDC00-\uD869\uDEDF\uD869\uDF00-\uD86D\uDF3F\uD86D\uDF40-\uD86E\uDC1F\uD86E\uDC20-\uD873\uDEAF\uD87E\uDC00-\uD87E\uDE1F]+";
    131. Pattern pattern = Pattern.compile(regex);
    132. return pattern.matcher(content).matches();
    133. }
    134. }
    JsonUtil.java
    1. public class JsonUtil {
    2. private final static String arg = "\"";
    3. /**
    4. * Map转成JSON字符串
    5. *
    6. * @param map
    7. * @return JSON
    8. */
    9. public static String mapToJsonString(Map map) {
    10. return CollectionUtils.isEmpty(map) ? "" : JSONObject.toJSONString(map).replace(arg,"'");
    11. }
    12. }

    SQL配置与执行:

    SqlConfiguration.java
    1. @Component("SqlConfiguration")
    2. @ConfigurationProperties(prefix = "jdbc-config")
    3. @Data
    4. public class SqlConfiguration {
    5. private String driver;
    6. private String url;
    7. private String userName;
    8. private String password;
    9. }
    SqlDataSourceConfiguration.java
    1. @Configuration
    2. @ConditionalOnBean(SqlConfiguration.class)
    3. @Slf4j
    4. public class SqlDataSourceConfiguration {
    5. @Resource
    6. private SqlConfiguration sqlConfiguration;
    7. @Bean("DriverManagerDataSource")
    8. @Scope(value = "singleton")
    9. public DriverManagerDataSource getDataSource(){
    10. DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
    11. driverManagerDataSource.setDriverClassName(sqlConfiguration.getDriver());
    12. driverManagerDataSource.setUrl(sqlConfiguration.getUrl());
    13. driverManagerDataSource.setUsername(sqlConfiguration.getUserName());
    14. driverManagerDataSource.setPassword(sqlConfiguration.getPassword());
    15. log.info("扫描生成自定义配置JDBC数据源:{}",sqlConfiguration.getUrl());
    16. return driverManagerDataSource;
    17. }
    18. }
    JdbcTransactionManagerConfiguration.java
    1. @Configuration
    2. @ConditionalOnBean({SqlDataSourceConfiguration.class})
    3. @Slf4j
    4. public class JdbcTransactionManagerConfiguration {
    5. @Resource
    6. private DriverManagerDataSource driverManagerDataSource;
    7. @Bean("JdbcTransactionManager")
    8. @Scope("singleton")
    9. public JdbcTransactionManager getJdbcTransactionManager(){
    10. JdbcTransactionManager jdbcTransactionManager = new JdbcTransactionManager();
    11. log.info("开始配置JDBC事务管理者");
    12. jdbcTransactionManager.setDataSource(driverManagerDataSource);
    13. jdbcTransactionManager.setRollbackOnCommitFailure(true);
    14. jdbcTransactionManager.setFailEarlyOnGlobalRollbackOnly(true);
    15. jdbcTransactionManager.setGlobalRollbackOnParticipationFailure(true);
    16. return jdbcTransactionManager;
    17. }
    18. }
    TransactionTemplateConfiguration.java
    1. @Configuration
    2. @Slf4j
    3. public class TransactionTemplateConfiguration {
    4. @Resource
    5. private JdbcTransactionManager jdbcTransactionManager;
    6. @Bean("ReadCommittedTransactionTemplate")
    7. @Scope("singleton")
    8. @ConditionalOnBean({JdbcTransactionManager.class})
    9. @Lazy
    10. public TransactionTemplate getReadCommittedTransactionTemplate(){
    11. TransactionTemplate transactionTemplate = new TransactionTemplate();
    12. log.info("生成事务模板,注入事务管理器,设置事务隔离级别为读已提交");
    13. transactionTemplate.setTransactionManager(jdbcTransactionManager);
    14. transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
    15. return transactionTemplate;
    16. }
    17. @Bean("ReadUnCommittedTransactionTemplate")
    18. @Scope("singleton")
    19. @ConditionalOnBean({JdbcTransactionManager.class})
    20. @Lazy
    21. public TransactionTemplate getReadUnCommittedTransactionTemplate(){
    22. TransactionTemplate transactionTemplate = new TransactionTemplate();
    23. log.info("生成事务模板,注入事务管理器,设置事务隔离级别为读未提交");
    24. transactionTemplate.setTransactionManager(jdbcTransactionManager);
    25. transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
    26. return transactionTemplate;
    27. }
    28. @Bean("RepeatableReadTransactionTemplate")
    29. @Scope("singleton")
    30. @ConditionalOnBean({JdbcTransactionManager.class})
    31. @Lazy
    32. public TransactionTemplate getRepeatableReadTransactionTemplate(){
    33. TransactionTemplate transactionTemplate = new TransactionTemplate();
    34. log.info("生成事务模板,注入事务管理器,设置事务隔离级别为可重复读");
    35. transactionTemplate.setTransactionManager(jdbcTransactionManager);
    36. transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
    37. return transactionTemplate;
    38. }
    39. @Bean("SerializableTransactionTemplate")
    40. @Scope("singleton")
    41. @ConditionalOnBean({JdbcTransactionManager.class})
    42. @Lazy
    43. public TransactionTemplate getSerializableTransactionTemplate(){
    44. TransactionTemplate transactionTemplate = new TransactionTemplate();
    45. log.info("生成事务模板,注入事务管理器,设置事务隔离级别为可串行化");
    46. transactionTemplate.setTransactionManager(jdbcTransactionManager);
    47. transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
    48. return transactionTemplate;
    49. }
    50. }
    SqlSpliceProvider.java
    1. public interface SqlSpliceProvider {
    2. /**
    3. * 拼接建表SQL
    4. *
    5. * @param columnEntityList excel的列属性列表
    6. * @param tableName 表名
    7. * @return SQL
    8. */
    9. StringBuffer spliceCreateTableSql(List columnEntityList, String tableName);
    10. /**
    11. * 拼接删表SQL
    12. *
    13. * @param tableName 表名
    14. * @return SQL
    15. */
    16. String dropTableSql(String tableName);
    17. /**
    18. * 拼接判断表存在SQL
    19. *
    20. * @param tableName 表名
    21. * @return SQL
    22. */
    23. String existsTableSql(String tableName);
    24. /**
    25. * 拼接插值SQL列表循环执行即可
    26. *
    27. * @param map 值map<行号,对应行的值LIST>
    28. * @param tableName 表名
    29. * @return SQL
    30. */
    31. List spliceInsertValueSql(Map> map, String tableName);
    32. }
    SqlSplicer.java
    1. @Service
    2. public class SqlSplicer implements SqlSpliceProvider {
    3. /**
    4. * 拼接建表SQL
    5. *
    6. * @param columnEntityList 列信息实体列表
    7. * @param tableName 表格名称
    8. * @return SQL
    9. */
    10. @Override
    11. public StringBuffer spliceCreateTableSql(List columnEntityList, String tableName) {
    12. StringBuffer stringBuffer = new StringBuffer();
    13. stringBuffer.append("CREATE TABLE ").append(SqlSpliceStringUtil.quotesHandle(SqlSpliceStringUtil.transferPinYin(tableName))).append(" ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自动主键',");
    14. /*扫描属性列表,填充建表SQL*/
    15. stringBuffer.append(scanColumnListToSql(columnEntityList));
    16. stringBuffer.append(" PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ");
    17. return stringBuffer;
    18. }
    19. /**
    20. * 删除数据表,防止表重复
    21. *
    22. * @param tableName 表名称
    23. * @return SQL
    24. */
    25. @Override
    26. public String dropTableSql(String tableName) {
    27. return "DROP TABLE IF EXISTS " + SqlSpliceStringUtil.quotesHandle(SqlSpliceStringUtil.transferPinYin(tableName));
    28. }
    29. /**
    30. * 查询数据表是否存在
    31. * @param tableName 表名称
    32. * @return SQL
    33. */
    34. @Override
    35. public String existsTableSql(String tableName) {
    36. return "SELECT * FROM information_schema.TABLES WHERE TABLE_NAME = " + SqlSpliceStringUtil.quotesHandle(SqlSpliceStringUtil.transferPinYin(tableName));
    37. }
    38. /**
    39. * 拼接插值SQL(单插入SQL集合)
    40. *
    41. * @param map 值实体列表Map
    42. * @param tableName 表名
    43. * @return 插值SQL
    44. */
    45. @Override
    46. public List spliceInsertValueSql(Map> map, String tableName) {
    47. List sqlList = new LinkedList<>();
    48. map.values().forEach(valueEntityList -> sqlList.add(scanValueListToSql(tableName, valueEntityList)));
    49. return sqlList;
    50. }
    51. /**
    52. * 拼接单一数据行值SQL
    53. *
    54. * @param tableName 表名
    55. * @param valueEntityList 一行数据值列表
    56. * @return SQL
    57. */
    58. private static String scanValueListToSql(String tableName, List valueEntityList) {
    59. StringBuilder stringBuffer = new StringBuilder();
    60. stringBuffer.append("INSERT INTO ").append(SqlSpliceStringUtil.quotesHandle(SqlSpliceStringUtil.transferPinYin(tableName)));
    61. stringBuffer.append(" VALUES( null,");
    62. for (ValueEntity element : valueEntityList) {
    63. if ((valueEntityList.indexOf(element) + 1) != valueEntityList.toArray().length) {
    64. stringBuffer.append(element.getValueOfString()).append(",");
    65. } else {
    66. stringBuffer.append(element.getValueOfString());
    67. }
    68. }
    69. stringBuffer.append(");");
    70. return stringBuffer.toString();
    71. }
    72. /**
    73. * 将列信息实体列表转SQL
    74. *
    75. * @param columnEntityList 列信息实体列表
    76. * @return 处理完成得列属性SQL串
    77. */
    78. private static String scanColumnListToSql(List columnEntityList) {
    79. StringBuilder fieldSql = new StringBuilder();
    80. for (ColumnEntity element : columnEntityList) {
    81. fieldSql.append(SqlSpliceStringUtil.quotesHandle(element.getColumnName())).append(element.getColumnSqlInfo());
    82. }
    83. return fieldSql.toString();
    84. }
    85. }
    SqlDataProvider.java
    1. public interface SqlDataProvider {
    2. /**
    3. * 执行非查询SQL
    4. *
    5. * @param sql
    6. */
    7. void executeSql(String sql);
    8. /**
    9. * 执行查询判断某些存在SQL
    10. *
    11. * @param sql
    12. * @return 是否存在的对象 为空则不存在
    13. */
    14. Object executeSqlAndGetReturn(String sql);
    15. /**
    16. * 执行查询SQL
    17. *
    18. * @param sql
    19. * @return 结果的Json字符串
    20. */
    21. String executeQuerySql(String sql);
    22. }
    SqlDataService.java
    1. @Service
    2. @Slf4j
    3. public class SqlDataService implements SqlDataProvider {
    4. @Resource
    5. private JdbcTemplate jdbcTemplate;
    6. @Qualifier("ReadCommittedTransactionTemplate")
    7. @Resource
    8. private TransactionTemplate transactionTemplate;
    9. @Override
    10. public void executeSql(String sql) {
    11. log.info("执行非查询操作SQL,开启事务执行:{}", sql);
    12. transactionTemplate.executeWithoutResult(status -> {
    13. try {
    14. jdbcTemplate.execute(sql);
    15. } catch (Exception e) {
    16. log.error("事务异常,开启回滚:{}", e.getMessage());
    17. status.setRollbackOnly();
    18. }
    19. });
    20. }
    21. @Override
    22. public Object executeSqlAndGetReturn(String sql) {
    23. log.info("执行查询SQL:{}", sql);
    24. return jdbcTemplate.queryForObject(sql, Object.class);
    25. }
    26. @Override
    27. public String executeQuerySql(String sql) {
    28. log.info("执行查询SQL:{}", sql);
    29. List> mapList = jdbcTemplate.queryForList(sql);
    30. if (CollectionUtils.isEmpty(mapList)) {
    31. return "";
    32. }
    33. List result = new LinkedList<>();
    34. mapList.forEach(map -> result.add(JsonUtil.mapToJsonString(map)));
    35. return result.toString();
    36. }
    37. }

    具体的讲解就不说了,分享代码案例,感兴趣的同学可以gitee上搜git@gitee.com:huanglinchun/resolve_excel_auto.git

  • 相关阅读:
    ENSP常用指令
    使用 SAP UI5 ABAP Repository 部署本地 SAP UI5 应用到 ABAP 服务器的单步调试
    数据压缩STC稀疏三元压缩算法复现
    【动手学深度学习】--文本预处理
    Excel 导出打不开
    文件夹复制功能的实现
    【Unity】万人同屏, 从入门到放弃之——多线程RVO避障
    【C++】类和对象 从入门到超神 (上)
    初识进程~
    vue 请求代理 proxy
  • 原文地址:https://blog.csdn.net/m0_59588838/article/details/132612093