需求:
假设我们现在有一个需求,需要快速拉取数据库的某些表建表语句,和数据,平时做备份之类;
我这边自己写了个工具,不多废话,也不整虚的,
直接看代码:
java
package com.hugh.javaMybatis.dbWorm;
/**
* @author Mr.qiuyebai
* @date 2024/4/1 20:08
* @VERSION 1.0.0
* @Describe
*/
import org.springframework.jdbc.BadSqlGrammarException;
import java.io.*;
import java.sql.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GetDbData {
private static Connection getConnection() throws SQLException, ClassNotFoundException {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://127.0.0.1:3306/monitor?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8";
String user = "root";
String password = "123456";
return DriverManager.getConnection(url, user, password);
}
public static void main(String[] args) throws FileNotFoundException {
String inputFile = "/a.txt";
String relativePath = "target/output.sql";
File file = new File(relativePath);
HashSet<String> set = new HashSet<String>();
set.add("");
InputStream inputStream = GetDbData.class.getResourceAsStream(inputFile);
if (inputStream == null) {
System.out.println("========退出");
return;
}
try (Connection connection = getConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
PrintWriter writer = new PrintWriter(new FileWriter(file))
) {
String line;
while ((line = reader.readLine()) != null) {
if ("".equals(line)) {
continue;
}
writer.println("-- " + line);
if (line.toUpperCase().startsWith("SHOW CREATE TABLE")) {
try (Statement stmt = connection.createStatement()) {
// String tableName = line.split(" ")[3].replace(";", "");
String tableName = getTableName(line.toUpperCase(), "TABLE");
ResultSet rs = stmt.executeQuery(line);
if (rs.next()) {
writer.println(rs.getString(2) + ";");
}
}
} else if (line.toUpperCase().startsWith("SELECT")) {
// 1. 拿到 select 后面,所有字段的类型并存起来,只查一遍,
// 2. select * 是全部字段,本功能只涉及select from 一个表
// 3. 执行该句sql,拿到结果,
// 4. 先打印 a.txt 的那个查询语句(写成注释形式,就是 加上 -- ),
// 5. 拼接 INSERT 语句,本质上来说,需要注意 哪些需要 加上 单引号
// 6. 最后空两行继续下一个 select 语句处理
//String tableName = line.substring(line.toUpperCase().indexOf("FROM") + 5).trim().replace(";", "");
String tableName = getTableName(line.toUpperCase(), "FROM");
// 获取字段的数据类型
Map<String, Integer> columnTypes = getColumnTypes(connection, tableName);
try (Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(line)) {
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
// 写入 SELECT 语句作为注释
// 对于结果集中的每一行,生成 INSERT 语句
while (rs.next()) {
StringBuilder columns = new StringBuilder();
StringBuilder values = new StringBuilder();
for (int i = 1; i <= columnCount; i++) {
if (i > 1) {
columns.append(", ");
values.append(", ");
}
columns.append(metaData.getColumnName(i));
int type = columnTypes.getOrDefault(metaData.getColumnName(i), Types.VARCHAR);
String value = rs.getString(i);
if (type == Types.VARCHAR || type == Types.CHAR || type == Types.LONGVARCHAR || type == Types.TIMESTAMP) {
if (value == null) {
values.append("null");
} else {
values.append("'").append(value.replace("'", "''")).append("'");
}
} else {
if (value == null) {
values.append("null");
} else {
values.append(value);
}
}
}
// 换行符号微调
// 为什么这样做:节省算力
if (set.contains(tableName)) {
values.toString().replaceAll("\r\n", "\\r\\n");
}
writer.printf("INSERT INTO %s (%s) VALUES (%s);\n", tableName, columns, values);
}
} catch (BadSqlGrammarException e) {
System.out.println("=======Bad Sql========");
} catch (Exception e) {
e.printStackTrace();
System.out.println("=====Exception!!!====");
}
}
writer.println();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取字段类型
*
* @param connection
* @param tableName
* @return
*/
private static Map<String, Integer> getColumnTypes(Connection connection, String tableName) {
Map<String, Integer> columnTypes = new HashMap<>();
DatabaseMetaData metaData = null;
try {
metaData = connection.getMetaData();
try (ResultSet rs = metaData.getColumns(null, null, tableName, null)) {
while (rs.next()) {
String columnName = rs.getString("COLUMN_NAME");
int dataType = rs.getInt("DATA_TYPE");
columnTypes.put(columnName, dataType);
}
}
return columnTypes;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取表名字
*
* @param line
* @param keyWord
* @return
*/
public static String getTableName(String line, String keyWord) {
String lowerLine = line.toLowerCase();
int keyWordIndex = lowerLine.indexOf(keyWord.toLowerCase());
if (keyWordIndex == -1) {
// 关键字未找到
return null;
}
// 找到关键字后,截取关键字后的字符串
String afterKeyWord = line.substring(keyWordIndex + keyWord.length()).trim();
// 使用正则表达式匹配第一个可能的表名
// 假设表名由字母、数字、下划线组成,并且可能以反引号包围
String regex = "^[`]?([a-zA-Z0-9_]+)[`]?";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(afterKeyWord);
if (matcher.find()) {
// 返回匹配到的表名
return matcher.group(1);
}
// 未找到合适的匹配
return null;
}
}
然后准备这样式的文件,就给导出建表语句和数据;
sql
SHOW CREATE TABLE sys_user;
SELECT * FROM sys_user;
SELECT * FROM sys_dept;
完工;
走过路过,点个赞,三连一下哈;
不知不觉,时间过去的很快,
感觉自己最近内耗比较严重,
前段时间找对象来着,被骗了不少米,
真艰难啊,,,
哈哈哈哈,,,
加油吧,好好活着🍀