|
@@ -0,0 +1,313 @@
|
|
|
+package com.example.bigsql.service;
|
|
|
+
|
|
|
+
|
|
|
+import cn.hutool.core.date.DatePattern;
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.io.FileUtil;
|
|
|
+import cn.hutool.core.util.ZipUtil;
|
|
|
+import com.example.bigsql.entity.UploadBigsqlFileRecordBaseVO;
|
|
|
+import com.example.bigsql.util.ExecuteShellUtil;
|
|
|
+import com.example.bigsql.util.JyDbUtil;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.io.*;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.nio.file.Paths;
|
|
|
+import java.sql.*;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 解析v3版大sql文件
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class CreateDatabasesByV3File {
|
|
|
+
|
|
|
+ private static boolean createTable(String databasesName, List<String> sqlStatements, Connection conn) {
|
|
|
+ try {
|
|
|
+ conn.setAutoCommit(false);
|
|
|
+ Statement statement = conn.createStatement();
|
|
|
+ sqlStatements.forEach(sql -> {
|
|
|
+ sql = sql.replace("EXISTS `", "EXISTS `" + databasesName + "`.`").replace(";", "");
|
|
|
+ sql = sql.replace("TABLE `", "TABLE `" + databasesName + "`.`").replace(";", "");
|
|
|
+ try {
|
|
|
+ statement.addBatch(sql);
|
|
|
+
|
|
|
+ } catch (SQLException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ int[] i = statement.executeBatch();
|
|
|
+ conn.commit();
|
|
|
+ System.out.println("成功执行语句:" + i.length);
|
|
|
+ return true;
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static boolean createDatabase(String tableName, Connection conn) {
|
|
|
+ try {
|
|
|
+ Statement statement = conn.createStatement();
|
|
|
+ statement.execute("CREATE DATABASE `" + tableName + "` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
|
|
+
|
|
|
+ System.out.printf("Database '%s' created successfully!%n", tableName);
|
|
|
+ return true;
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.out.printf("Database '%s' created error!%n", tableName);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static List<UploadBigsqlFileRecordBaseVO> queryRecords() throws SQLException {
|
|
|
+ //连接mysql
|
|
|
+ Connection conn = null;
|
|
|
+ PreparedStatement ps = null;
|
|
|
+ ResultSet rs = null;
|
|
|
+ try {
|
|
|
+ String url = "jdbc:mysql://192.168.12.241:19400/jiayueCloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true";
|
|
|
+ //加载数据库驱动
|
|
|
+ Class.forName("com.mysql.cj.jdbc.Driver");
|
|
|
+ conn = DriverManager.getConnection(url, "root", "QJtgNR52+*L^E809-3");
|
|
|
+ String sql = "SELECT * FROM dc_upload_bigsql_file_record d WHERE d.status = '0'";
|
|
|
+ ps = conn.prepareStatement(sql);
|
|
|
+ rs = ps.executeQuery();
|
|
|
+ List<UploadBigsqlFileRecordBaseVO> uploadBigsqlFileRecordList = new ArrayList<>();
|
|
|
+ while (rs.next()) {
|
|
|
+ UploadBigsqlFileRecordBaseVO uploadBigsqlFileRecord = new UploadBigsqlFileRecordBaseVO();
|
|
|
+ uploadBigsqlFileRecord.setId(rs.getInt("id"));
|
|
|
+ uploadBigsqlFileRecord.setFileName(rs.getString("file_name"));
|
|
|
+ uploadBigsqlFileRecord.setRemark(rs.getString("remark"));
|
|
|
+ uploadBigsqlFileRecord.setStatus(rs.getString("status"));
|
|
|
+ uploadBigsqlFileRecordList.add(uploadBigsqlFileRecord);
|
|
|
+ }
|
|
|
+ return uploadBigsqlFileRecordList;
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ } finally {
|
|
|
+ if (ps != null) {
|
|
|
+ ps.close();
|
|
|
+ }
|
|
|
+ if (rs != null) {
|
|
|
+ rs.close();
|
|
|
+ }
|
|
|
+ if (conn != null) {
|
|
|
+ conn.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private static void updateRecords(int id, String status, String dbName) throws SQLException {
|
|
|
+ //连接mysql
|
|
|
+ Connection conn = null;
|
|
|
+ PreparedStatement ps = null;
|
|
|
+ try {
|
|
|
+ String url = "jdbc:mysql://192.168.12.241:19400/jiayueCloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true";
|
|
|
+ //加载数据库驱动
|
|
|
+ Class.forName("com.mysql.cj.jdbc.Driver");
|
|
|
+ conn = DriverManager.getConnection(url, "root", "QJtgNR52+*L^E809-3");
|
|
|
+ String sql = "UPDATE dc_upload_bigsql_file_record set status = '" + status + "' , db_name = '" + dbName + "' WHERE id = " + id + ";";
|
|
|
+ ps = conn.prepareStatement(sql);
|
|
|
+ ps.executeUpdate();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ } finally {
|
|
|
+ if (ps != null) {
|
|
|
+ ps.close();
|
|
|
+ }
|
|
|
+ if (conn != null) {
|
|
|
+ conn.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static File[] searchFile(File folder, final String keyWord) {// 递归查找包含关键字的文件
|
|
|
+
|
|
|
+ File[] subFolders = folder.listFiles(new FileFilter() {// 运用内部匿名类获得文件
|
|
|
+ @Override
|
|
|
+ public boolean accept(File pathname) {// 实现FileFilter类的accept方法
|
|
|
+ // 目录或文件包含关键字
|
|
|
+ return pathname.isDirectory()
|
|
|
+ || (pathname.isFile() && pathname.getName().toLowerCase().contains(keyWord.toLowerCase()));
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ List<File> result = new ArrayList<File>();// 声明一个集合
|
|
|
+ for (int i = 0; i < subFolders.length; i++) {// 循环显示文件夹或文件
|
|
|
+ if (subFolders[i].isFile()) {// 如果是文件则将文件添加到结果列表中
|
|
|
+ result.add(subFolders[i]);
|
|
|
+ } else {// 如果是文件夹,则递归调用本方法,然后把所有的文件加到结果列表中
|
|
|
+ File[] foldResult = searchFile(subFolders[i], keyWord);
|
|
|
+ Collections.addAll(result, foldResult);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ File[] files = new File[result.size()];// 声明文件数组,长度为集合的长度
|
|
|
+ result.toArray(files);// 集合数组化
|
|
|
+ return files;
|
|
|
+ }
|
|
|
+
|
|
|
+ //把insert语句分割成csv文件
|
|
|
+ public static void spliteFileToCsv(String line, Map<String, FileWriter> fileWriterMap, String csvFilePath) {
|
|
|
+ String outputFilePath = ".csv";
|
|
|
+ try {
|
|
|
+ if (line.trim().startsWith("INSERT")) {
|
|
|
+ String tableName = line.substring(13, line.indexOf("` VALUES"));
|
|
|
+ if (null == fileWriterMap.get(tableName)) {
|
|
|
+ fileWriterMap.put(tableName, new FileWriter(csvFilePath + tableName + outputFilePath));
|
|
|
+ }
|
|
|
+ // 解析SQL语句,提取数据
|
|
|
+ String[] data = parseSQLLine(line);
|
|
|
+
|
|
|
+ if (data != null) {
|
|
|
+ // 将数据以CSV格式写入文件
|
|
|
+ fileWriterMap.get(tableName).write(String.join(",", data));
|
|
|
+ fileWriterMap.get(tableName).write("\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析SQL语句中的数据
|
|
|
+ private static String[] parseSQLLine(String line) {
|
|
|
+ if (line.trim().startsWith("INSERT")) {
|
|
|
+ //解析INSERT语句中的数据
|
|
|
+ int startIndex = line.indexOf("(");
|
|
|
+ int endIndex = line.indexOf(")");
|
|
|
+ if (startIndex == -1 || endIndex == -1) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String data = line.substring(startIndex + 1, endIndex).replaceAll("'", "");
|
|
|
+
|
|
|
+ return data.replace(", ", ",").replace("\\", "").split(",");
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 读取文件 并创建数据库和表
|
|
|
+ */
|
|
|
+ public void redSqlZip() throws Exception {
|
|
|
+ //未解析的sql压缩包包
|
|
|
+ List<UploadBigsqlFileRecordBaseVO> list = queryRecords();
|
|
|
+ log.info("找到" + list.size() + "条待恢复记录");
|
|
|
+ //sql zip包存放路径
|
|
|
+ //String path = "/Users/xiaowang/个人/";
|
|
|
+ String path = "/home/bigsql/";
|
|
|
+ Map<String, FileWriter> fileWriterMap = new HashMap<>();
|
|
|
+ File file = new File(path);
|
|
|
+ for (UploadBigsqlFileRecordBaseVO uploadBigsqlFileRecordBaseVO : list) {
|
|
|
+ File[] files = searchFile(file, uploadBigsqlFileRecordBaseVO.getFileName());
|
|
|
+ //根据文件名查找文件 正常没有数据或只有一条数据
|
|
|
+ for (File f : files) {
|
|
|
+ log.info("开始解析sql文件,文件名:" + f.getName());
|
|
|
+ //场站编号
|
|
|
+ String name = f.getName().substring(0, 6);
|
|
|
+ //String csvFilePath = "/Users/xiaowang/个人/csvdir/" + name + File.separator;
|
|
|
+ String csvFilePath = "/home/bigsql/csvdir/" + name + File.separator;
|
|
|
+ String sqlPath = "/home/bigsql/sqldir/";
|
|
|
+ //判断csvFilePath这个目录是否存在 如果不存在则创建目录
|
|
|
+ if (!new File(csvFilePath).exists()) {
|
|
|
+ new File(csvFilePath).mkdirs();
|
|
|
+ }
|
|
|
+ if (!new File(sqlPath).exists()) {
|
|
|
+ new File(sqlPath).mkdirs();
|
|
|
+ }
|
|
|
+ String databasesName = "";
|
|
|
+ //获取文件输入流
|
|
|
+ BufferedInputStream input = new BufferedInputStream(Files.newInputStream(Paths.get(f.getPath())));
|
|
|
+ //扫描解压目录下的sql文件 正常没有数据或只有一条数据
|
|
|
+ ZipUtil.unzip(f.getPath(), sqlPath, StandardCharsets.UTF_8);
|
|
|
+ File sFile = new File(sqlPath);
|
|
|
+ File[] sFiles = searchFile(sFile, ".sql");
|
|
|
+ if (sFiles.length == 0) {
|
|
|
+ log.error(f.getName() + "压缩文件为空");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ //循环遍历
|
|
|
+ try {
|
|
|
+ try (BufferedReader reader = new BufferedReader(new FileReader(sFiles[0]))) {
|
|
|
+ List<String> sqlStatements = new ArrayList<>();
|
|
|
+ StringBuilder statementBuilder = new StringBuilder();
|
|
|
+ String line;
|
|
|
+ int lineSize = 0;
|
|
|
+ while ((line = reader.readLine()) != null) {
|
|
|
+ if (line.startsWith("Navicat") || line.startsWith("/")
|
|
|
+ || line.startsWith("INSERT") || line.startsWith("--") || line.startsWith("#")
|
|
|
+ || line.startsWith("//")) {
|
|
|
+ lineSize++;
|
|
|
+ //sql内的数据转换成csv文件
|
|
|
+ spliteFileToCsv(line, fileWriterMap, csvFilePath);
|
|
|
+ continue; // Skip comments
|
|
|
+ }
|
|
|
+ if (line.endsWith(";")) {
|
|
|
+ statementBuilder.append(line); // Remove semicolon
|
|
|
+ sqlStatements.add(statementBuilder.toString().trim()); // Add to list
|
|
|
+ statementBuilder.setLength(0); // Reset statement buffer
|
|
|
+ } else {
|
|
|
+ statementBuilder.append(line).append(" ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sqlStatements = sqlStatements.stream().filter(s -> s.startsWith("CREATE") || s.startsWith("DROP")).collect(Collectors.toList());
|
|
|
+ databasesName = "ipfcst_" + name + "_" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_FORMAT);
|
|
|
+ Connection conn = JyDbUtil.conn;
|
|
|
+ if (createDatabase(databasesName, conn)) {
|
|
|
+ if (createTable(databasesName, sqlStatements, conn)) {
|
|
|
+ log.info("执行数据库和数据表创建成功,其中数据共:" + lineSize);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ updateRecords(uploadBigsqlFileRecordBaseVO.getId(), "2", databasesName);
|
|
|
+ throw new RuntimeException("读取Sql文件失败: " + f.getName(), e);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ input.close();
|
|
|
+ //修改cloud数据库表里的状态
|
|
|
+ updateRecords(uploadBigsqlFileRecordBaseVO.getId(), "1", databasesName);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.info("读取zip文件时异常" + e);
|
|
|
+ } finally {
|
|
|
+ input.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("表结构导入完毕,开始进行表数据导入");
|
|
|
+
|
|
|
+ File csvFile = new File(csvFilePath);
|
|
|
+ File[] csvFiles = csvFile.listFiles();
|
|
|
+ if (csvFiles != null) {
|
|
|
+ for (File csv : csvFiles) {
|
|
|
+ insertData(databasesName, csv);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.info("数据导入完毕!!!");
|
|
|
+ FileUtil.del(sqlPath);
|
|
|
+ FileUtil.del(csvFilePath);
|
|
|
+ FileUtil.move(f, new File(path + File.separator + "backUps" + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + File.separator + f.getName()), true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void insertData(String databasesName, File table) throws Exception {
|
|
|
+
|
|
|
+ String[] tableNames = table.getName().split("\\.");
|
|
|
+ log.info(tableNames[0] + "表数据开始向" + databasesName + "数据库导入");
|
|
|
+ ExecuteShellUtil executeShellUtil = ExecuteShellUtil.getInstance();
|
|
|
+ executeShellUtil.init("192.168.12.10", 22, "root", "Jydl*3377");
|
|
|
+ //表名
|
|
|
+ executeShellUtil.execCmd("mysqlsh mysql://root:mysql_T7yN3E@127.0.0.1:19306 -- util import-table " + table.getPath() + " --schema=" + databasesName + " --table=" + tableNames[0] + " --dialect=csv-unix --threads=10");
|
|
|
+ //executeShellUtil.execCmd("mysqlsh mysql://root:123456@127.0.0.1:3306 -- util import-table D:\\bigsql\\csvdir\\J00307\\" + table.getName() + " --schema=" + databasesName + " --table=" + tableNames[0] + " --dialect=csv-unix --threads=10");
|
|
|
+ log.info("表" + tableNames[0] + "导入完毕");
|
|
|
+ executeShellUtil.close();
|
|
|
+ }
|
|
|
+}
|