优化通配符逆向工程
This commit is contained in:
+94
-28
@@ -9,11 +9,10 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
@@ -40,58 +39,130 @@ public class MyBatisGeneratorService {
|
||||
|
||||
/**
|
||||
* 根据表名通配符生成Mapper文件
|
||||
* 先查询数据库中匹配的表,再进行逆向工程
|
||||
*
|
||||
* @param pattern 表名通配符(如 user_%)
|
||||
* @param overwrite 是否覆盖已有文件
|
||||
* @return 生成结果信息
|
||||
*/
|
||||
public String generateByPattern(String pattern, boolean overwrite) throws Exception {
|
||||
List<String> patterns = new ArrayList<>();
|
||||
patterns.add(pattern);
|
||||
return generateInternal(patterns, overwrite);
|
||||
// 查询数据库中匹配通配符的表
|
||||
List<String> matchedTables = queryTablesByPattern(pattern);
|
||||
|
||||
if (matchedTables.isEmpty()) {
|
||||
return "未找到匹配通配符 [" + pattern + "] 的表";
|
||||
}
|
||||
|
||||
log.info("通配符 [{}] 匹配到 {} 张表: {}", pattern, matchedTables.size(), matchedTables);
|
||||
return generateInternal(matchedTables, overwrite);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据通配符查询数据库中的表
|
||||
*
|
||||
* @param pattern 表名通配符(支持 % 和 _ 通配符)
|
||||
* @return 匹配的表名列表
|
||||
*/
|
||||
public List<String> queryTablesByPattern(String pattern) throws Exception {
|
||||
List<String> tables = new ArrayList<>();
|
||||
Properties props = getConfigurationProperties();
|
||||
|
||||
String url = props.getProperty("db_url");
|
||||
String username = props.getProperty("db_username");
|
||||
String password = props.getProperty("db_password");
|
||||
|
||||
// 从URL中提取数据库名
|
||||
String dbName = extractDatabaseName(url);
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(url, username, password)) {
|
||||
// 查询匹配的表名
|
||||
String sql = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME LIKE ?";
|
||||
try (PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setString(1, dbName);
|
||||
ps.setString(2, pattern);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
tables.add(rs.getString("TABLE_NAME"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据库中所有表
|
||||
*
|
||||
* @return 所有表名列表
|
||||
*/
|
||||
public List<String> queryAllTables() throws Exception {
|
||||
List<String> tables = new ArrayList<>();
|
||||
Properties props = getConfigurationProperties();
|
||||
|
||||
String url = props.getProperty("db_url");
|
||||
String username = props.getProperty("db_username");
|
||||
String password = props.getProperty("db_password");
|
||||
|
||||
String dbName = extractDatabaseName(url);
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(url, username, password)) {
|
||||
String sql = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME";
|
||||
try (PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setString(1, dbName);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
tables.add(rs.getString("TABLE_NAME"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从JDBC URL中提取数据库名
|
||||
*/
|
||||
private String extractDatabaseName(String url) {
|
||||
// jdbc:mysql://localhost:3306/disburse?xxx -> disburse
|
||||
int start = url.lastIndexOf('/');
|
||||
int end = url.indexOf('?', start);
|
||||
if (end == -1) {
|
||||
end = url.length();
|
||||
}
|
||||
return url.substring(start + 1, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部生成方法
|
||||
*
|
||||
* @param tableNames 表名列表
|
||||
* @param overwrite 是否覆盖已有文件
|
||||
* @return 生成结果信息
|
||||
*/
|
||||
private String generateInternal(List<String> tableNames, boolean overwrite) throws Exception {
|
||||
// 动态修改配置文件中的表配置
|
||||
File tempConfigFile = createTempConfigWithTables(tableNames);
|
||||
|
||||
try {
|
||||
// 解析临时配置文件
|
||||
List<String> warnings = new ArrayList<>();
|
||||
|
||||
// 设置使用 JDK 内置 XML 解析器
|
||||
System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
|
||||
System.setProperty("javax.xml.parsers.SAXParserFactory", "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
|
||||
|
||||
ConfigurationParser parser = new ConfigurationParser(warnings);
|
||||
Configuration configuration = parser.parseConfiguration(tempConfigFile);
|
||||
|
||||
// 执行生成
|
||||
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
|
||||
MyBatisGenerator generator = new MyBatisGenerator(configuration, callback, warnings);
|
||||
generator.generate(null, null, null, true);
|
||||
|
||||
// 收集结果信息
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append("成功生成 ").append(tableNames.size()).append(" 张表的Mapper文件\n");
|
||||
if (!warnings.isEmpty()) {
|
||||
result.append("生成完成,有以下警告:\n");
|
||||
result.append("警告信息:\n");
|
||||
for (String warning : warnings) {
|
||||
result.append("- ").append(warning).append("\n");
|
||||
}
|
||||
} else {
|
||||
result.append("生成成功!");
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
} finally {
|
||||
// 删除临时文件
|
||||
if (tempConfigFile.exists()) {
|
||||
tempConfigFile.delete();
|
||||
}
|
||||
@@ -99,10 +170,9 @@ public class MyBatisGeneratorService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建临时配置文件,包含指定的表配置
|
||||
* 创建临时配置文件
|
||||
*/
|
||||
private File createTempConfigWithTables(List<String> tableNames) throws Exception {
|
||||
// 读取原始配置文件内容
|
||||
InputStream is = getClass().getClassLoader().getResourceAsStream(CONFIG_FILE);
|
||||
if (is == null) {
|
||||
throw new RuntimeException("无法找到配置文件: " + CONFIG_FILE);
|
||||
@@ -118,11 +188,10 @@ public class MyBatisGeneratorService {
|
||||
content = sb.toString();
|
||||
}
|
||||
|
||||
// 使用正则表达式移除原有的 table 元素
|
||||
// 匹配 <table ... /> 或 <table ...></table>
|
||||
Pattern tablePattern = Pattern.compile(
|
||||
// 移除原有的 table 元素
|
||||
java.util.regex.Pattern tablePattern = java.util.regex.Pattern.compile(
|
||||
"<table[^>]*/>|<table[^>]*>.*?</table>",
|
||||
Pattern.DOTALL
|
||||
java.util.regex.Pattern.DOTALL
|
||||
);
|
||||
content = tablePattern.matcher(content).replaceAll("");
|
||||
|
||||
@@ -140,10 +209,8 @@ public class MyBatisGeneratorService {
|
||||
.append(" selectByExampleQueryId=\"false\"/>\n\n");
|
||||
}
|
||||
|
||||
// 在 </context> 标签前插入新的 table 元素
|
||||
content = content.replace("</context>", tableElements.toString() + " </context>");
|
||||
|
||||
// 写入临时文件
|
||||
File tempFile = File.createTempFile("mybatis-generator-temp", ".xml");
|
||||
try (FileOutputStream fos = new FileOutputStream(tempFile)) {
|
||||
fos.write(content.getBytes(StandardCharsets.UTF_8));
|
||||
@@ -154,7 +221,6 @@ public class MyBatisGeneratorService {
|
||||
|
||||
/**
|
||||
* 根据表名生成实体类名
|
||||
* 例如:user_info -> UserInfoPO
|
||||
*/
|
||||
private String generateDomainObjectName(String tableName) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
@@ -22,7 +22,8 @@ public class MyBatisGeneratorHandler extends AbstractMenuHandler {
|
||||
"1. 根据表名生成(单表)",
|
||||
"2. 根据表名生成(多表,逗号分隔)",
|
||||
"3. 根据表名通配符生成(如 user_%)",
|
||||
"4. 查看当前配置信息",
|
||||
"4. 查看数据库所有表",
|
||||
"5. 查看当前配置信息",
|
||||
"0. 返回上级菜单"
|
||||
};
|
||||
|
||||
@@ -64,6 +65,9 @@ public class MyBatisGeneratorHandler extends AbstractMenuHandler {
|
||||
generateByPattern(scanner);
|
||||
break;
|
||||
case 4:
|
||||
showAllTables();
|
||||
break;
|
||||
case 5:
|
||||
showConfiguration();
|
||||
break;
|
||||
default:
|
||||
@@ -131,12 +135,46 @@ public class MyBatisGeneratorHandler extends AbstractMenuHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
info("开始根据通配符 [{}] 生成Mapper文件", pattern);
|
||||
String result = generatorService.generateByPattern(pattern, true);
|
||||
// 先查询匹配的表
|
||||
List<String> matchedTables = generatorService.queryTablesByPattern(pattern);
|
||||
if (matchedTables.isEmpty()) {
|
||||
System.out.println("未找到匹配通配符 [" + pattern + "] 的表");
|
||||
return;
|
||||
}
|
||||
|
||||
// 展示匹配到的表
|
||||
System.out.println("匹配到 " + matchedTables.size() + " 张表:");
|
||||
for (int i = 0; i < matchedTables.size(); i++) {
|
||||
System.out.println(" " + (i + 1) + ". " + matchedTables.get(i));
|
||||
}
|
||||
|
||||
// 确认是否继续
|
||||
System.out.print("是否继续生成?(y/n): ");
|
||||
String confirm = scanner.nextLine().trim().toLowerCase();
|
||||
if (!"y".equals(confirm)) {
|
||||
System.out.println("已取消生成");
|
||||
return;
|
||||
}
|
||||
|
||||
info("开始根据通配符 [{}] 生成 {} 张表的Mapper文件", pattern, matchedTables.size());
|
||||
String result = generatorService.generateByTableNames(matchedTables, true);
|
||||
System.out.println(result);
|
||||
printSuccess("生成完成");
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示数据库中所有表
|
||||
*/
|
||||
private void showAllTables() throws Exception {
|
||||
List<String> tables = generatorService.queryAllTables();
|
||||
System.out.println();
|
||||
System.out.println("========== 数据库所有表(共 " + tables.size() + " 张)==========");
|
||||
for (int i = 0; i < tables.size(); i++) {
|
||||
System.out.println(" " + (i + 1) + ". " + tables.get(i));
|
||||
}
|
||||
System.out.println("=================================");
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示当前配置信息
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user