20260722173146

This commit is contained in:
oneao committed 2026-07-22 17:31:48 +08:00
1 parent e9f099f044
commit d04fad24ed
24 files changed
+1309 -422

No files matched your search

@@ -3,6 +3,7 @@ package cn.g3soft.fmsapi.controller;
import cn.g3soft.fmsapi.service.DataSaveService;
import cn.g3soft.fmsapi.service.DataService;
import cn.g3soft.fmsapi.utils.ApiResponse;
import cn.g3soft.fmsapi.utils.ParamUtils;
import cn.g3soft.fmsapi.utils.snowflake.idgen.IdGenerator;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
@@ -58,4 +59,11 @@ public class DataController {
public ApiResponse<Long> nextId() {
return ApiResponse.success(IdGenerator.nextId());
}
@PostMapping("/describe")
public ApiResponse<List<Map<String, Object>>> describe(
@RequestBody(required = false) Map<String, Object> params
) throws SQLException {
return ApiResponse.success(dataService.describe(ParamUtils.getRequiredString(params, "table")));
}
}
@@ -126,7 +126,7 @@ public class DataSaveService {
switch (action) {
case "delete" -> dbUtils.delete(connection, table, keyColumn, rows.get(index));
case "update" -> dbUtils.update(connection, table, keyColumn, rows.get(index));
case "insert" -> dbUtils.insert(connection, table, rows.get(index));
case "insert" -> dbUtils.insert(connection, table, keyColumn, rows.get(index));
default -> throw new IllegalArgumentException("不支持的保存操作: " + action);
}
} catch (SQLException exception) {
@@ -4,8 +4,11 @@ import cn.g3soft.fmsapi.exception.BusinessException;
import cn.g3soft.fmsapi.utils.DbUtils;
import cn.g3soft.fmsapi.utils.ParamUtils;
import jakarta.annotation.Resource;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Service;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;
@@ -17,6 +20,18 @@ public class DataService {
@Resource
private DbUtils dbUtils;
@Resource
private DataSource dataSource;
public List<Map<String, Object>> describe(String table) throws SQLException {
Connection connection = DataSourceUtils.getConnection(dataSource);
try {
return dbUtils.describeColumns(connection, table);
} finally {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
public List<Map<String, Object>> loadData(Map<String, Object> params) throws SQLException {
return dbUtils.loadData(
ParamUtils.getRequiredString(params, "view_name"),
@@ -2,6 +2,7 @@ package cn.g3soft.fmsapi.utils;
import cn.g3soft.fmsapi.database.OrgDataSourceManager;
import cn.g3soft.fmsapi.exception.BusinessException;
import cn.g3soft.fmsapi.utils.snowflake.idgen.IdGenerator;
import jakarta.annotation.Resource;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Component;
@@ -222,9 +223,11 @@ public class DbUtils {
|| metadata.isReadOnly(index)
|| "timestamp".equalsIgnoreCase(typeName)
|| "rowversion".equalsIgnoreCase(typeName);
boolean nullable = metadata.isNullable(index) != ResultSetMetaData.columnNoNulls;
int size = metadata.getPrecision(index);
columns.put(
normalizedName,
new ColumnMetadata(columnName, normalizedName, !generated)
new ColumnMetadata(columnName, normalizedName, !generated, typeName, nullable, size)
);
}
}
@@ -241,12 +244,54 @@ public class DbUtils {
return table.columnsByName().get(normalizeName(requiredFieldName));
}
/**
* 读取表或视图的列结构(列名、类型、可空、长度),用于前端同步字段等场景。
* 入参 table 会经后端标识符校验,不会拼接到 SQL。
*/
public List<Map<String, Object>> describeColumns(
Connection connection,
String tableName
) throws SQLException {
TableMetadata table = loadTableMetadata(connection, tableName);
List<Map<String, Object>> result = new ArrayList<>();
for (ColumnMetadata column : table.columnsByName().values()) {
Map<String, Object> describe = new LinkedHashMap<>();
describe.put("name", column.name());
describe.put("type", column.typeName());
describe.put("nullable", column.nullable());
describe.put("size", column.size());
result.add(describe);
}
return result;
}
private boolean shouldAssignKey(Object keyValue) {
if (keyValue == null) {
return true;
}
if (keyValue instanceof Number number) {
return number.longValue() < 0;
}
if (keyValue instanceof String text && !text.isBlank()) {
try {
return Long.parseLong(text) < 0;
} catch (NumberFormatException ignored) {
return false;
}
}
return false;
}
public int insert(
Connection connection,
TableMetadata table,
ColumnMetadata keyColumn,
Map<String, Object> row
) throws SQLException {
Map<String, Object> normalizedRow = normalizeRow(row);
if (keyColumn != null && shouldAssignKey(normalizedRow.get(keyColumn.normalizedName()))) {
normalizedRow.put(keyColumn.normalizedName(), IdGenerator.nextId());
}
LinkedHashMap<ColumnMetadata, Object> values = writableValues(
table,
normalizedRow,
@@ -600,7 +645,10 @@ public class DbUtils {
public record ColumnMetadata(
String name,
String normalizedName,
boolean writable
boolean writable,
String typeName,
boolean nullable,
int size
) {
}