💩 重构抽象层次;解决资源泄漏;优化元数据获取性能
This commit is contained in:
parent
5ef135de32
commit
1e07831818
|
@ -1,6 +1,6 @@
|
|||
package cn.bunny.controller;
|
||||
|
||||
import cn.bunny.core.factory.ConcreteSqlParserDatabaseInfoService;
|
||||
import cn.bunny.core.factory.SqlMetadataProvider;
|
||||
import cn.bunny.domain.entity.ColumnMetaData;
|
||||
import cn.bunny.domain.entity.TableMetaData;
|
||||
import cn.bunny.domain.result.Result;
|
||||
|
@ -19,7 +19,7 @@ import java.util.List;
|
|||
@RequiredArgsConstructor
|
||||
public class SqlParserController {
|
||||
|
||||
private final ConcreteSqlParserDatabaseInfoService sqlParserService;
|
||||
private final SqlMetadataProvider sqlParserService;
|
||||
|
||||
@Operation(summary = "解析SQL成表信息", description = "解析SQL成表信息")
|
||||
@PostMapping("tableInfo")
|
||||
|
@ -31,7 +31,7 @@ public class SqlParserController {
|
|||
@Operation(summary = "解析SQL成列数据", description = "解析SQL成列数据")
|
||||
@PostMapping("columnMetaData")
|
||||
public Result<List<ColumnMetaData>> columnMetaData(String sql) {
|
||||
List<ColumnMetaData> vo = sqlParserService.tableColumnInfo(sql);
|
||||
List<ColumnMetaData> vo = sqlParserService.getColumnInfoList(sql);
|
||||
return Result.success(vo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package cn.bunny.controller;
|
||||
|
||||
import cn.bunny.core.factory.ConcreteDatabaseInfoService;
|
||||
import cn.bunny.core.factory.DatabaseMetadataProvider;
|
||||
import cn.bunny.domain.entity.ColumnMetaData;
|
||||
import cn.bunny.domain.entity.DatabaseInfoMetaData;
|
||||
import cn.bunny.domain.entity.TableMetaData;
|
||||
|
@ -22,7 +22,7 @@ import java.util.List;
|
|||
public class TableController {
|
||||
|
||||
private final TableService tableService;
|
||||
private final ConcreteDatabaseInfoService concreteDatabaseInfoService;
|
||||
private final DatabaseMetadataProvider databaseMetadataProvider;
|
||||
|
||||
@Operation(summary = "当前数据库信息", description = "当前连接的数据库信息")
|
||||
@GetMapping("databaseInfoMetaData")
|
||||
|
@ -34,21 +34,21 @@ public class TableController {
|
|||
@Operation(summary = "数据库所有的表", description = "获取[当前/所有]数据库表")
|
||||
@GetMapping("databaseTableList")
|
||||
public Result<List<TableMetaData>> databaseTableList(String dbName) {
|
||||
List<TableMetaData> list = concreteDatabaseInfoService.databaseTableList(dbName);
|
||||
List<TableMetaData> list = databaseMetadataProvider.getTableMetadataBatch(dbName);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@Operation(summary = "表属性", description = "获取当前查询表属性")
|
||||
@GetMapping("tableMetaData")
|
||||
public Result<TableMetaData> tableMetaData(String tableName) {
|
||||
TableMetaData tableMetaData = concreteDatabaseInfoService.getTableMetadata(tableName);
|
||||
TableMetaData tableMetaData = databaseMetadataProvider.getTableMetadata(tableName);
|
||||
return Result.success(tableMetaData);
|
||||
}
|
||||
|
||||
@Operation(summary = "表的列属性", description = "获取当前查询表中列属性")
|
||||
@GetMapping("tableColumnInfo")
|
||||
public Result<List<ColumnMetaData>> tableColumnInfo(String tableName) {
|
||||
List<ColumnMetaData> columnInfo = concreteDatabaseInfoService.tableColumnInfo(tableName);
|
||||
List<ColumnMetaData> columnInfo = databaseMetadataProvider.getColumnInfoList(tableName);
|
||||
return Result.success(columnInfo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
package cn.bunny.core.factory;
|
||||
|
||||
import cn.bunny.domain.entity.ColumnMetaData;
|
||||
import cn.bunny.domain.entity.TableMetaData;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Component
|
||||
public abstract class AbstractDatabaseInfo {
|
||||
|
||||
public DataSource dataSource;
|
||||
|
||||
@Autowired
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表的所有主键列名
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return 主键列名的集合
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Set<String> findPrimaryKeyColumns(String tableName) {
|
||||
// 主键的key
|
||||
Set<String> primaryKeys = new HashSet<>();
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
|
||||
// 当前表的主键
|
||||
ResultSet pkResultSet = metaData.getPrimaryKeys(null, null, tableName);
|
||||
|
||||
while (pkResultSet.next()) {
|
||||
// 列字段
|
||||
String columnName = pkResultSet.getString("COLUMN_NAME").toLowerCase();
|
||||
primaryKeys.add(columnName);
|
||||
}
|
||||
|
||||
return primaryKeys;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 sql 表信息
|
||||
*
|
||||
* @param name 表名称或sql
|
||||
* @return 表西悉尼
|
||||
*/
|
||||
public abstract TableMetaData getTableMetadata(String name);
|
||||
|
||||
/**
|
||||
* 获取当前表的列属性
|
||||
*
|
||||
* @param name 表名称或sql
|
||||
* @return 当前表所有的列内容
|
||||
*/
|
||||
public abstract List<ColumnMetaData> tableColumnInfo(String name);
|
||||
|
||||
}
|
|
@ -3,23 +3,57 @@ package cn.bunny.core.factory;
|
|||
import cn.bunny.domain.entity.ColumnMetaData;
|
||||
import cn.bunny.domain.entity.DatabaseInfoMetaData;
|
||||
import cn.bunny.domain.entity.TableMetaData;
|
||||
import cn.bunny.exception.GeneratorCodeException;
|
||||
import cn.bunny.utils.TypeConvertUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
public class ConcreteDatabaseInfoService extends AbstractDatabaseInfo {
|
||||
@RequiredArgsConstructor
|
||||
public class DatabaseMetadataProvider implements IMetadataProvider {
|
||||
|
||||
private final DataSource dataSource;
|
||||
@Value("${bunny.master.database}")
|
||||
private String currentDatabase;
|
||||
|
||||
/**
|
||||
* 获取表的所有主键列名
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return 主键列名的集合
|
||||
*/
|
||||
public Set<String> getPrimaryKeys(String tableName) {
|
||||
// 主键的key
|
||||
Set<String> primaryKeys = new HashSet<>();
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
|
||||
// 当前表的主键
|
||||
ResultSet pkResultSet = metaData.getPrimaryKeys(null, null, tableName);
|
||||
|
||||
while (pkResultSet.next()) {
|
||||
// 列字段
|
||||
String columnName = pkResultSet.getString("COLUMN_NAME").toLowerCase();
|
||||
primaryKeys.add(columnName);
|
||||
}
|
||||
|
||||
return primaryKeys;
|
||||
} catch (SQLException e) {
|
||||
throw new GeneratorCodeException("获取主键失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库所有的信息
|
||||
*
|
||||
|
@ -45,17 +79,17 @@ public class ConcreteDatabaseInfoService extends AbstractDatabaseInfo {
|
|||
/**
|
||||
* 解析 sql 表信息
|
||||
*
|
||||
* @param tableName 表名称或sql
|
||||
* @param identifier 表名称或sql
|
||||
* @return 表西悉尼
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public TableMetaData getTableMetadata(String tableName) {
|
||||
public TableMetaData getTableMetadata(String identifier) {
|
||||
TableMetaData tableMetaData;
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
ResultSet tables = metaData.getTables(null, null, tableName, new String[]{"TABLE"});
|
||||
ResultSet tables = metaData.getTables(null, null, identifier, new String[]{"TABLE"});
|
||||
|
||||
// 获取表的注释信息
|
||||
if (tables.next()) {
|
||||
|
@ -69,7 +103,7 @@ public class ConcreteDatabaseInfoService extends AbstractDatabaseInfo {
|
|||
String tableType = tables.getString("TABLE_TYPE");
|
||||
|
||||
tableMetaData = TableMetaData.builder()
|
||||
.tableName(tableName)
|
||||
.tableName(identifier)
|
||||
.comment(remarks)
|
||||
.tableCat(tableCat)
|
||||
.tableType(tableType)
|
||||
|
@ -88,12 +122,12 @@ public class ConcreteDatabaseInfoService extends AbstractDatabaseInfo {
|
|||
* @return 所有表信息
|
||||
*/
|
||||
@SneakyThrows
|
||||
public List<TableMetaData> databaseTableList(String dbName) {
|
||||
public List<TableMetaData> getTableMetadataBatch(String dbName) {
|
||||
// 当前数据库数据库所有的表
|
||||
List<TableMetaData> allTableInfo = new ArrayList<>();
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
try (Connection conn = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = conn.getMetaData();
|
||||
|
||||
// 当前数据库中所有的表
|
||||
ResultSet tables = metaData.getTables(dbName, null, "%", new String[]{"TABLE"});
|
||||
|
@ -115,20 +149,20 @@ public class ConcreteDatabaseInfoService extends AbstractDatabaseInfo {
|
|||
/**
|
||||
* 获取当前表的列属性
|
||||
*
|
||||
* @param tableName 表名称或sql
|
||||
* @param identifier 表名称或sql
|
||||
* @return 当前表所有的列内容
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public List<ColumnMetaData> tableColumnInfo(String tableName) {
|
||||
public List<ColumnMetaData> getColumnInfoList(String identifier) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
Map<String, ColumnMetaData> map = new LinkedHashMap<>();
|
||||
// 当前表的主键
|
||||
Set<String> primaryKeyColumns = findPrimaryKeyColumns(tableName);
|
||||
Set<String> primaryKeyColumns = getPrimaryKeys(identifier);
|
||||
|
||||
// 当前表的列信息
|
||||
try (ResultSet columnsRs = metaData.getColumns(null, null, tableName, null)) {
|
||||
try (ResultSet columnsRs = metaData.getColumns(null, null, identifier, null)) {
|
||||
while (columnsRs.next()) {
|
||||
ColumnMetaData column = new ColumnMetaData();
|
||||
// 列字段
|
|
@ -0,0 +1,26 @@
|
|||
package cn.bunny.core.factory;
|
||||
|
||||
import cn.bunny.domain.entity.ColumnMetaData;
|
||||
import cn.bunny.domain.entity.TableMetaData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IMetadataProvider {
|
||||
|
||||
/**
|
||||
* 解析 sql 表信息
|
||||
*
|
||||
* @param identifier 表名称或sql
|
||||
* @return 表西悉尼
|
||||
*/
|
||||
TableMetaData getTableMetadata(String identifier);
|
||||
|
||||
/**
|
||||
* 获取当前表的列属性
|
||||
*
|
||||
* @param identifier 表名称或sql
|
||||
* @return 当前表所有的列内容
|
||||
*/
|
||||
List<ColumnMetaData> getColumnInfoList(String identifier);
|
||||
|
||||
}
|
|
@ -16,24 +16,24 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
@Component
|
||||
public class ConcreteSqlParserDatabaseInfoService extends AbstractDatabaseInfo {
|
||||
public class SqlMetadataProvider implements IMetadataProvider {
|
||||
|
||||
/**
|
||||
* 解析 sql 表信息
|
||||
* 先解析SQL语句,解析列字段信息
|
||||
*
|
||||
* @param sql 表名称或sql
|
||||
* @param identifier 表名称或sql
|
||||
* @return 表西悉尼
|
||||
* @see CCJSqlParserUtil 使用这个工具进行SQL的解析
|
||||
*/
|
||||
@Override
|
||||
public TableMetaData getTableMetadata(String sql) {
|
||||
public TableMetaData getTableMetadata(String identifier) {
|
||||
TableMetaData tableInfo = new TableMetaData();
|
||||
|
||||
// 解析sql
|
||||
Statement statement;
|
||||
try {
|
||||
statement = CCJSqlParserUtil.parse(sql);
|
||||
statement = CCJSqlParserUtil.parse(identifier);
|
||||
} catch (JSQLParserException e) {
|
||||
throw new GeneratorCodeException("SQL解析失败");
|
||||
}
|
||||
|
@ -61,15 +61,15 @@ public class ConcreteSqlParserDatabaseInfoService extends AbstractDatabaseInfo {
|
|||
/**
|
||||
* 获取当前表的列属性
|
||||
*
|
||||
* @param sql 表名称或sql
|
||||
* @param identifier 表名称或sql
|
||||
* @return 当前表所有的列内容
|
||||
*/
|
||||
@Override
|
||||
public List<ColumnMetaData> tableColumnInfo(String sql) {
|
||||
public List<ColumnMetaData> getColumnInfoList(String identifier) {
|
||||
// 解析sql
|
||||
Statement statement;
|
||||
try {
|
||||
statement = CCJSqlParserUtil.parse(sql);
|
||||
statement = CCJSqlParserUtil.parse(identifier);
|
||||
} catch (JSQLParserException e) {
|
||||
throw new RuntimeException("SQL解析失败");
|
||||
}
|
|
@ -15,7 +15,7 @@ import java.util.Date;
|
|||
* 使用模板方法,方便扩展
|
||||
* 如果需要继承 AbstractVmsGenerator
|
||||
*/
|
||||
public class VmsArgumentDtoBaseVmsGeneratorTemplate extends AbstractVmsGeneratorTemplate {
|
||||
public class VmsArgumentDtoBaseTemplateGenerator extends AbstractTemplateGenerator {
|
||||
|
||||
private final VmsArgumentDto dto;
|
||||
private final String path;
|
||||
|
@ -26,7 +26,7 @@ public class VmsArgumentDtoBaseVmsGeneratorTemplate extends AbstractVmsGenerator
|
|||
* @param path 当前路径
|
||||
* @param tableMetaData 表名称
|
||||
*/
|
||||
public VmsArgumentDtoBaseVmsGeneratorTemplate(VmsArgumentDto dto, String path, TableMetaData tableMetaData) {
|
||||
public VmsArgumentDtoBaseTemplateGenerator(VmsArgumentDto dto, String path, TableMetaData tableMetaData) {
|
||||
this.dto = dto;
|
||||
this.path = path;
|
||||
this.tableMetaData = tableMetaData;
|
|
@ -1,6 +1,6 @@
|
|||
package cn.bunny.service.impl;
|
||||
|
||||
import cn.bunny.core.factory.ConcreteDatabaseInfoService;
|
||||
import cn.bunny.core.factory.DatabaseMetadataProvider;
|
||||
import cn.bunny.domain.entity.DatabaseInfoMetaData;
|
||||
import cn.bunny.domain.entity.TableMetaData;
|
||||
import cn.bunny.service.TableService;
|
||||
|
@ -15,7 +15,7 @@ import java.util.stream.Collectors;
|
|||
@RequiredArgsConstructor
|
||||
public class TableServiceImpl implements TableService {
|
||||
|
||||
private final ConcreteDatabaseInfoService concreteDatabaseInfoService;
|
||||
private final DatabaseMetadataProvider databaseMetadataProvider;
|
||||
|
||||
/**
|
||||
* 数据库所有的信息
|
||||
|
@ -25,7 +25,7 @@ public class TableServiceImpl implements TableService {
|
|||
@SneakyThrows
|
||||
@Override
|
||||
public DatabaseInfoMetaData databaseInfoMetaData() {
|
||||
List<TableMetaData> databaseTableList = concreteDatabaseInfoService.databaseTableList(null);
|
||||
List<TableMetaData> databaseTableList = databaseMetadataProvider.getTableMetadataBatch(null);
|
||||
|
||||
// 将当前数据库表分组,以数据库名称为key
|
||||
List<TableMetaData> databaseList = databaseTableList.stream()
|
||||
|
@ -37,7 +37,7 @@ public class TableServiceImpl implements TableService {
|
|||
return tableInfoVo;
|
||||
}).toList();
|
||||
|
||||
DatabaseInfoMetaData databaseInfoMetaData = concreteDatabaseInfoService.databaseInfoMetaData();
|
||||
DatabaseInfoMetaData databaseInfoMetaData = databaseMetadataProvider.databaseInfoMetaData();
|
||||
databaseInfoMetaData.setDatabaseList(databaseList);
|
||||
|
||||
return databaseInfoMetaData;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package cn.bunny.service.impl.vms;
|
||||
|
||||
import cn.bunny.core.factory.ConcreteDatabaseInfoService;
|
||||
import cn.bunny.core.factory.ConcreteSqlParserDatabaseInfoService;
|
||||
import cn.bunny.core.template.VmsArgumentDtoBaseVmsGeneratorTemplate;
|
||||
import cn.bunny.core.factory.DatabaseMetadataProvider;
|
||||
import cn.bunny.core.factory.SqlMetadataProvider;
|
||||
import cn.bunny.core.template.VmsArgumentDtoBaseTemplateGenerator;
|
||||
import cn.bunny.domain.dto.VmsArgumentDto;
|
||||
import cn.bunny.domain.entity.ColumnMetaData;
|
||||
import cn.bunny.domain.entity.TableMetaData;
|
||||
|
@ -25,8 +25,8 @@ import java.util.stream.Collectors;
|
|||
@RequiredArgsConstructor
|
||||
public class VmsCodeGeneratorService {
|
||||
|
||||
private final ConcreteDatabaseInfoService databaseInfoCore;
|
||||
private final ConcreteSqlParserDatabaseInfoService sqlParserDatabaseInfo;
|
||||
private final DatabaseMetadataProvider databaseInfoCore;
|
||||
private final SqlMetadataProvider sqlParserDatabaseInfo;
|
||||
|
||||
/**
|
||||
* 根据DTO生成代码模板
|
||||
|
@ -44,7 +44,7 @@ public class VmsCodeGeneratorService {
|
|||
|
||||
return dto.getPath().stream()
|
||||
.map(path -> {
|
||||
VmsArgumentDtoBaseVmsGeneratorTemplate generator = new VmsArgumentDtoBaseVmsGeneratorTemplate(dto, path, tableMetaData);
|
||||
VmsArgumentDtoBaseTemplateGenerator generator = new VmsArgumentDtoBaseTemplateGenerator(dto, path, tableMetaData);
|
||||
StringWriter writer = generator.generatorCodeTemplate(tableMetaData, columnInfoList);
|
||||
String processedPath = VmsUtil.handleVmFilename(path, tableMetaData.getTableName());
|
||||
|
||||
|
@ -84,8 +84,8 @@ public class VmsCodeGeneratorService {
|
|||
*/
|
||||
private List<ColumnMetaData> getColumnInfoList(String sql, String tableName) {
|
||||
return StringUtils.hasText(sql)
|
||||
? sqlParserDatabaseInfo.tableColumnInfo(sql)
|
||||
: databaseInfoCore.tableColumnInfo(tableName).stream().distinct().toList();
|
||||
? sqlParserDatabaseInfo.getColumnInfoList(sql)
|
||||
: databaseInfoCore.getColumnInfoList(tableName).stream().distinct().toList();
|
||||
}
|
||||
|
||||
}
|
|
@ -14,7 +14,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
@SpringBootTest
|
||||
class ConcreteDatabaseInfoServiceCoreTest {
|
||||
class DatabaseMetadataProviderCoreTest {
|
||||
|
||||
String tableName = "sys_i18n";
|
||||
|
Loading…
Reference in New Issue