feat: 重构数据中枢工作台与接入管理
- 新增统一的数据源、目录、纳管表与 Excel 处理后端能力 - 重建管理端数据中枢工作台并替换旧表管理页面 - 补充数据中枢迁移脚本、连接器底座与说明字段支持
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
package tech.easyflow.datacenter.meta.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.handler.FastjsonTypeHandler;
|
||||
import tech.easyflow.common.entity.DateEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@Table(value = "tb_datacenter_catalog", comment = "数据中心逻辑库/命名空间")
|
||||
public class DatacenterCatalog extends DateEntity implements Serializable {
|
||||
|
||||
@Id(keyType = KeyType.Generator, value = "snowFlakeId", comment = "主键")
|
||||
private BigInteger id;
|
||||
@Column(comment = "部门ID")
|
||||
private BigInteger deptId;
|
||||
@Column(tenantId = true, comment = "租户ID")
|
||||
private BigInteger tenantId;
|
||||
@Column(comment = "数据源ID")
|
||||
private BigInteger sourceId;
|
||||
@Column(comment = "目录名")
|
||||
private String catalogName;
|
||||
@Column(comment = "目录描述")
|
||||
private String catalogDesc;
|
||||
@Column(comment = "目录类型")
|
||||
private String catalogType;
|
||||
@Column(comment = "状态")
|
||||
private Integer status;
|
||||
@Column(typeHandler = FastjsonTypeHandler.class, comment = "扩展项")
|
||||
private Map<String, Object> options;
|
||||
@Column(comment = "创建时间")
|
||||
private Date created;
|
||||
@Column(comment = "创建人")
|
||||
private BigInteger createdBy;
|
||||
@Column(comment = "修改时间")
|
||||
private Date modified;
|
||||
@Column(comment = "修改人")
|
||||
private BigInteger modifiedBy;
|
||||
|
||||
public BigInteger getId() { return id; }
|
||||
public void setId(BigInteger id) { this.id = id; }
|
||||
public BigInteger getDeptId() { return deptId; }
|
||||
public void setDeptId(BigInteger deptId) { this.deptId = deptId; }
|
||||
public BigInteger getTenantId() { return tenantId; }
|
||||
public void setTenantId(BigInteger tenantId) { this.tenantId = tenantId; }
|
||||
public BigInteger getSourceId() { return sourceId; }
|
||||
public void setSourceId(BigInteger sourceId) { this.sourceId = sourceId; }
|
||||
public String getCatalogName() { return catalogName; }
|
||||
public void setCatalogName(String catalogName) { this.catalogName = catalogName; }
|
||||
public String getCatalogDesc() { return catalogDesc; }
|
||||
public void setCatalogDesc(String catalogDesc) { this.catalogDesc = catalogDesc; }
|
||||
public String getCatalogType() { return catalogType; }
|
||||
public void setCatalogType(String catalogType) { this.catalogType = catalogType; }
|
||||
public Integer getStatus() { return status; }
|
||||
public void setStatus(Integer status) { this.status = status; }
|
||||
public Map<String, Object> getOptions() { return options; }
|
||||
public void setOptions(Map<String, Object> options) { this.options = options; }
|
||||
@Override
|
||||
public Date getCreated() { return created; }
|
||||
@Override
|
||||
public void setCreated(Date created) { this.created = created; }
|
||||
public BigInteger getCreatedBy() { return createdBy; }
|
||||
public void setCreatedBy(BigInteger createdBy) { this.createdBy = createdBy; }
|
||||
@Override
|
||||
public Date getModified() { return modified; }
|
||||
@Override
|
||||
public void setModified(Date modified) { this.modified = modified; }
|
||||
public BigInteger getModifiedBy() { return modifiedBy; }
|
||||
public void setModifiedBy(BigInteger modifiedBy) { this.modifiedBy = modifiedBy; }
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package tech.easyflow.datacenter.meta.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.handler.FastjsonTypeHandler;
|
||||
import tech.easyflow.common.entity.DateEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@Table(value = "tb_datacenter_dataset_version", comment = "数据集版本")
|
||||
public class DatacenterDatasetVersion extends DateEntity implements Serializable {
|
||||
@Id(keyType = KeyType.Generator, value = "snowFlakeId")
|
||||
private BigInteger id;
|
||||
@Column(comment = "部门ID")
|
||||
private BigInteger deptId;
|
||||
@Column(tenantId = true, comment = "租户ID")
|
||||
private BigInteger tenantId;
|
||||
@Column(comment = "表ID")
|
||||
private BigInteger tableId;
|
||||
@Column(comment = "版本号")
|
||||
private Integer versionNo;
|
||||
@Column(comment = "版本标签")
|
||||
private String versionLabel;
|
||||
@Column(comment = "物化表名")
|
||||
private String materializedTable;
|
||||
@Column(typeHandler = FastjsonTypeHandler.class, comment = "版本快照")
|
||||
private Map<String, Object> snapshotJson;
|
||||
@Column(comment = "状态")
|
||||
private Integer status;
|
||||
@Column(comment = "创建时间")
|
||||
private Date created;
|
||||
@Column(comment = "创建人")
|
||||
private BigInteger createdBy;
|
||||
@Column(comment = "修改时间")
|
||||
private Date modified;
|
||||
@Column(comment = "修改人")
|
||||
private BigInteger modifiedBy;
|
||||
|
||||
public BigInteger getId() { return id; }
|
||||
public void setId(BigInteger id) { this.id = id; }
|
||||
public BigInteger getDeptId() { return deptId; }
|
||||
public void setDeptId(BigInteger deptId) { this.deptId = deptId; }
|
||||
public BigInteger getTenantId() { return tenantId; }
|
||||
public void setTenantId(BigInteger tenantId) { this.tenantId = tenantId; }
|
||||
public BigInteger getTableId() { return tableId; }
|
||||
public void setTableId(BigInteger tableId) { this.tableId = tableId; }
|
||||
public Integer getVersionNo() { return versionNo; }
|
||||
public void setVersionNo(Integer versionNo) { this.versionNo = versionNo; }
|
||||
public String getVersionLabel() { return versionLabel; }
|
||||
public void setVersionLabel(String versionLabel) { this.versionLabel = versionLabel; }
|
||||
public String getMaterializedTable() { return materializedTable; }
|
||||
public void setMaterializedTable(String materializedTable) { this.materializedTable = materializedTable; }
|
||||
public Map<String, Object> getSnapshotJson() { return snapshotJson; }
|
||||
public void setSnapshotJson(Map<String, Object> snapshotJson) { this.snapshotJson = snapshotJson; }
|
||||
public Integer getStatus() { return status; }
|
||||
public void setStatus(Integer status) { this.status = status; }
|
||||
@Override public Date getCreated() { return created; }
|
||||
@Override public void setCreated(Date created) { this.created = created; }
|
||||
public BigInteger getCreatedBy() { return createdBy; }
|
||||
public void setCreatedBy(BigInteger createdBy) { this.createdBy = createdBy; }
|
||||
@Override public Date getModified() { return modified; }
|
||||
@Override public void setModified(Date modified) { this.modified = modified; }
|
||||
public BigInteger getModifiedBy() { return modifiedBy; }
|
||||
public void setModifiedBy(BigInteger modifiedBy) { this.modifiedBy = modifiedBy; }
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package tech.easyflow.datacenter.meta.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.handler.FastjsonTypeHandler;
|
||||
import tech.easyflow.common.entity.DateEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@Table(value = "tb_datacenter_derived_table", comment = "数据中心派生表关系")
|
||||
public class DatacenterDerivedTable extends DateEntity implements Serializable {
|
||||
@Id(keyType = KeyType.Generator, value = "snowFlakeId")
|
||||
private BigInteger id;
|
||||
@Column(comment = "部门ID")
|
||||
private BigInteger deptId;
|
||||
@Column(tenantId = true, comment = "租户ID")
|
||||
private BigInteger tenantId;
|
||||
@Column(comment = "源表ID")
|
||||
private BigInteger sourceTableId;
|
||||
@Column(comment = "派生表ID")
|
||||
private BigInteger derivedTableId;
|
||||
@Column(comment = "派生类型")
|
||||
private String deriveType;
|
||||
@Column(typeHandler = FastjsonTypeHandler.class, comment = "派生配置")
|
||||
private Map<String, Object> deriveConfigJson;
|
||||
@Column(comment = "状态")
|
||||
private Integer status;
|
||||
@Column(comment = "创建时间")
|
||||
private Date created;
|
||||
@Column(comment = "创建人")
|
||||
private BigInteger createdBy;
|
||||
@Column(comment = "修改时间")
|
||||
private Date modified;
|
||||
@Column(comment = "修改人")
|
||||
private BigInteger modifiedBy;
|
||||
|
||||
public BigInteger getId() { return id; }
|
||||
public void setId(BigInteger id) { this.id = id; }
|
||||
public BigInteger getDeptId() { return deptId; }
|
||||
public void setDeptId(BigInteger deptId) { this.deptId = deptId; }
|
||||
public BigInteger getTenantId() { return tenantId; }
|
||||
public void setTenantId(BigInteger tenantId) { this.tenantId = tenantId; }
|
||||
public BigInteger getSourceTableId() { return sourceTableId; }
|
||||
public void setSourceTableId(BigInteger sourceTableId) { this.sourceTableId = sourceTableId; }
|
||||
public BigInteger getDerivedTableId() { return derivedTableId; }
|
||||
public void setDerivedTableId(BigInteger derivedTableId) { this.derivedTableId = derivedTableId; }
|
||||
public String getDeriveType() { return deriveType; }
|
||||
public void setDeriveType(String deriveType) { this.deriveType = deriveType; }
|
||||
public Map<String, Object> getDeriveConfigJson() { return deriveConfigJson; }
|
||||
public void setDeriveConfigJson(Map<String, Object> deriveConfigJson) { this.deriveConfigJson = deriveConfigJson; }
|
||||
public Integer getStatus() { return status; }
|
||||
public void setStatus(Integer status) { this.status = status; }
|
||||
@Override public Date getCreated() { return created; }
|
||||
@Override public void setCreated(Date created) { this.created = created; }
|
||||
public BigInteger getCreatedBy() { return createdBy; }
|
||||
public void setCreatedBy(BigInteger createdBy) { this.createdBy = createdBy; }
|
||||
@Override public Date getModified() { return modified; }
|
||||
@Override public void setModified(Date modified) { this.modified = modified; }
|
||||
public BigInteger getModifiedBy() { return modifiedBy; }
|
||||
public void setModifiedBy(BigInteger modifiedBy) { this.modifiedBy = modifiedBy; }
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package tech.easyflow.datacenter.meta.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.handler.FastjsonTypeHandler;
|
||||
import tech.easyflow.common.entity.DateEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@Table(value = "tb_datacenter_import_job", comment = "数据中心导入任务")
|
||||
public class DatacenterImportJob extends DateEntity implements Serializable {
|
||||
@Id(keyType = KeyType.Generator, value = "snowFlakeId")
|
||||
private BigInteger id;
|
||||
@Column(comment = "部门ID")
|
||||
private BigInteger deptId;
|
||||
@Column(tenantId = true, comment = "租户ID")
|
||||
private BigInteger tenantId;
|
||||
@Column(comment = "数据源ID")
|
||||
private BigInteger sourceId;
|
||||
@Column(comment = "目录ID")
|
||||
private BigInteger catalogId;
|
||||
@Column(comment = "表ID")
|
||||
private BigInteger tableId;
|
||||
@Column(comment = "任务类型")
|
||||
private String jobType;
|
||||
@Column(comment = "文件名")
|
||||
private String fileName;
|
||||
@Column(comment = "文件存储路径")
|
||||
private String storagePath;
|
||||
@Column(comment = "任务状态")
|
||||
private String status;
|
||||
@Column(comment = "总行数")
|
||||
private Long totalRows;
|
||||
@Column(comment = "成功行数")
|
||||
private Long successRows;
|
||||
@Column(comment = "失败行数")
|
||||
private Long errorRows;
|
||||
@Column(comment = "错误摘要")
|
||||
private String errorSummary;
|
||||
@Column(typeHandler = FastjsonTypeHandler.class, comment = "任务载荷")
|
||||
private Map<String, Object> payloadJson;
|
||||
@Column(comment = "开始时间")
|
||||
private Date startedAt;
|
||||
@Column(comment = "结束时间")
|
||||
private Date finishedAt;
|
||||
@Column(comment = "创建时间")
|
||||
private Date created;
|
||||
@Column(comment = "创建人")
|
||||
private BigInteger createdBy;
|
||||
@Column(comment = "修改时间")
|
||||
private Date modified;
|
||||
@Column(comment = "修改人")
|
||||
private BigInteger modifiedBy;
|
||||
|
||||
public BigInteger getId() { return id; }
|
||||
public void setId(BigInteger id) { this.id = id; }
|
||||
public BigInteger getDeptId() { return deptId; }
|
||||
public void setDeptId(BigInteger deptId) { this.deptId = deptId; }
|
||||
public BigInteger getTenantId() { return tenantId; }
|
||||
public void setTenantId(BigInteger tenantId) { this.tenantId = tenantId; }
|
||||
public BigInteger getSourceId() { return sourceId; }
|
||||
public void setSourceId(BigInteger sourceId) { this.sourceId = sourceId; }
|
||||
public BigInteger getCatalogId() { return catalogId; }
|
||||
public void setCatalogId(BigInteger catalogId) { this.catalogId = catalogId; }
|
||||
public BigInteger getTableId() { return tableId; }
|
||||
public void setTableId(BigInteger tableId) { this.tableId = tableId; }
|
||||
public String getJobType() { return jobType; }
|
||||
public void setJobType(String jobType) { this.jobType = jobType; }
|
||||
public String getFileName() { return fileName; }
|
||||
public void setFileName(String fileName) { this.fileName = fileName; }
|
||||
public String getStoragePath() { return storagePath; }
|
||||
public void setStoragePath(String storagePath) { this.storagePath = storagePath; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public Long getTotalRows() { return totalRows; }
|
||||
public void setTotalRows(Long totalRows) { this.totalRows = totalRows; }
|
||||
public Long getSuccessRows() { return successRows; }
|
||||
public void setSuccessRows(Long successRows) { this.successRows = successRows; }
|
||||
public Long getErrorRows() { return errorRows; }
|
||||
public void setErrorRows(Long errorRows) { this.errorRows = errorRows; }
|
||||
public String getErrorSummary() { return errorSummary; }
|
||||
public void setErrorSummary(String errorSummary) { this.errorSummary = errorSummary; }
|
||||
public Map<String, Object> getPayloadJson() { return payloadJson; }
|
||||
public void setPayloadJson(Map<String, Object> payloadJson) { this.payloadJson = payloadJson; }
|
||||
public Date getStartedAt() { return startedAt; }
|
||||
public void setStartedAt(Date startedAt) { this.startedAt = startedAt; }
|
||||
public Date getFinishedAt() { return finishedAt; }
|
||||
public void setFinishedAt(Date finishedAt) { this.finishedAt = finishedAt; }
|
||||
@Override public Date getCreated() { return created; }
|
||||
@Override public void setCreated(Date created) { this.created = created; }
|
||||
public BigInteger getCreatedBy() { return createdBy; }
|
||||
public void setCreatedBy(BigInteger createdBy) { this.createdBy = createdBy; }
|
||||
@Override public Date getModified() { return modified; }
|
||||
@Override public void setModified(Date modified) { this.modified = modified; }
|
||||
public BigInteger getModifiedBy() { return modifiedBy; }
|
||||
public void setModifiedBy(BigInteger modifiedBy) { this.modifiedBy = modifiedBy; }
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package tech.easyflow.datacenter.meta.entity;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.handler.FastjsonTypeHandler;
|
||||
import tech.easyflow.common.entity.DateEntity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@Table(value = "tb_datacenter_source", comment = "数据中心数据源")
|
||||
public class DatacenterSource extends DateEntity implements Serializable {
|
||||
|
||||
@Id(keyType = KeyType.Generator, value = "snowFlakeId", comment = "主键")
|
||||
private BigInteger id;
|
||||
@Column(comment = "部门ID")
|
||||
private BigInteger deptId;
|
||||
@Column(tenantId = true, comment = "租户ID")
|
||||
private BigInteger tenantId;
|
||||
@Column(comment = "数据源名称")
|
||||
private String sourceName;
|
||||
@Column(comment = "数据源编码")
|
||||
private String sourceCode;
|
||||
@Column(comment = "数据源类型")
|
||||
private String sourceType;
|
||||
@Column(comment = "访问模式")
|
||||
private String accessMode;
|
||||
@Column(comment = "是否内置")
|
||||
private Integer builtinFlag;
|
||||
@Column(comment = "驱动类名")
|
||||
private String driverClassName;
|
||||
@Column(comment = "JDBC URL")
|
||||
private String jdbcUrl;
|
||||
@Column(comment = "主机")
|
||||
private String host;
|
||||
@Column(comment = "端口")
|
||||
private Integer port;
|
||||
@Column(comment = "数据库名")
|
||||
private String databaseName;
|
||||
@Column(comment = "Schema名")
|
||||
private String schemaName;
|
||||
@Column(comment = "用户名")
|
||||
private String username;
|
||||
@Column(comment = "凭据密文")
|
||||
private String credentialCipher;
|
||||
@Column(typeHandler = FastjsonTypeHandler.class, comment = "连接配置")
|
||||
private Map<String, Object> configJson;
|
||||
@Column(typeHandler = FastjsonTypeHandler.class, comment = "能力声明")
|
||||
private Map<String, Object> capabilitiesJson;
|
||||
@Column(comment = "最近测试状态")
|
||||
private String lastTestStatus;
|
||||
@Column(comment = "最近测试信息")
|
||||
private String lastTestMessage;
|
||||
@Column(comment = "最近测试时间")
|
||||
private Date lastTestedAt;
|
||||
@Column(comment = "状态")
|
||||
private Integer status;
|
||||
@Column(typeHandler = FastjsonTypeHandler.class, comment = "扩展项")
|
||||
private Map<String, Object> options;
|
||||
@Column(comment = "创建时间")
|
||||
private Date created;
|
||||
@Column(comment = "创建人")
|
||||
private BigInteger createdBy;
|
||||
@Column(comment = "修改时间")
|
||||
private Date modified;
|
||||
@Column(comment = "修改人")
|
||||
private BigInteger modifiedBy;
|
||||
|
||||
public BigInteger getId() { return id; }
|
||||
public void setId(BigInteger id) { this.id = id; }
|
||||
public BigInteger getDeptId() { return deptId; }
|
||||
public void setDeptId(BigInteger deptId) { this.deptId = deptId; }
|
||||
public BigInteger getTenantId() { return tenantId; }
|
||||
public void setTenantId(BigInteger tenantId) { this.tenantId = tenantId; }
|
||||
public String getSourceName() { return sourceName; }
|
||||
public void setSourceName(String sourceName) { this.sourceName = sourceName; }
|
||||
public String getSourceCode() { return sourceCode; }
|
||||
public void setSourceCode(String sourceCode) { this.sourceCode = sourceCode; }
|
||||
public String getSourceType() { return sourceType; }
|
||||
public void setSourceType(String sourceType) { this.sourceType = sourceType; }
|
||||
public String getAccessMode() { return accessMode; }
|
||||
public void setAccessMode(String accessMode) { this.accessMode = accessMode; }
|
||||
public Integer getBuiltinFlag() { return builtinFlag; }
|
||||
public void setBuiltinFlag(Integer builtinFlag) { this.builtinFlag = builtinFlag; }
|
||||
public String getDriverClassName() { return driverClassName; }
|
||||
public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; }
|
||||
public String getJdbcUrl() { return jdbcUrl; }
|
||||
public void setJdbcUrl(String jdbcUrl) { this.jdbcUrl = jdbcUrl; }
|
||||
public String getHost() { return host; }
|
||||
public void setHost(String host) { this.host = host; }
|
||||
public Integer getPort() { return port; }
|
||||
public void setPort(Integer port) { this.port = port; }
|
||||
public String getDatabaseName() { return databaseName; }
|
||||
public void setDatabaseName(String databaseName) { this.databaseName = databaseName; }
|
||||
public String getSchemaName() { return schemaName; }
|
||||
public void setSchemaName(String schemaName) { this.schemaName = schemaName; }
|
||||
public String getUsername() { return username; }
|
||||
public void setUsername(String username) { this.username = username; }
|
||||
public String getCredentialCipher() { return credentialCipher; }
|
||||
public void setCredentialCipher(String credentialCipher) { this.credentialCipher = credentialCipher; }
|
||||
public Map<String, Object> getConfigJson() { return configJson; }
|
||||
public void setConfigJson(Map<String, Object> configJson) { this.configJson = configJson; }
|
||||
public Map<String, Object> getCapabilitiesJson() { return capabilitiesJson; }
|
||||
public void setCapabilitiesJson(Map<String, Object> capabilitiesJson) { this.capabilitiesJson = capabilitiesJson; }
|
||||
public String getLastTestStatus() { return lastTestStatus; }
|
||||
public void setLastTestStatus(String lastTestStatus) { this.lastTestStatus = lastTestStatus; }
|
||||
public String getLastTestMessage() { return lastTestMessage; }
|
||||
public void setLastTestMessage(String lastTestMessage) { this.lastTestMessage = lastTestMessage; }
|
||||
public Date getLastTestedAt() { return lastTestedAt; }
|
||||
public void setLastTestedAt(Date lastTestedAt) { this.lastTestedAt = lastTestedAt; }
|
||||
public Integer getStatus() { return status; }
|
||||
public void setStatus(Integer status) { this.status = status; }
|
||||
public Map<String, Object> getOptions() { return options; }
|
||||
public void setOptions(Map<String, Object> options) { this.options = options; }
|
||||
@Override
|
||||
public Date getCreated() { return created; }
|
||||
@Override
|
||||
public void setCreated(Date created) { this.created = created; }
|
||||
public BigInteger getCreatedBy() { return createdBy; }
|
||||
public void setCreatedBy(BigInteger createdBy) { this.createdBy = createdBy; }
|
||||
@Override
|
||||
public Date getModified() { return modified; }
|
||||
@Override
|
||||
public void setModified(Date modified) { this.modified = modified; }
|
||||
public BigInteger getModifiedBy() { return modifiedBy; }
|
||||
public void setModifiedBy(BigInteger modifiedBy) { this.modifiedBy = modifiedBy; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package tech.easyflow.datacenter.meta.enums;
|
||||
|
||||
public enum DatacenterAccessMode {
|
||||
READ_ONLY,
|
||||
READ_WRITE
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package tech.easyflow.datacenter.meta.enums;
|
||||
|
||||
public enum DatacenterCapability {
|
||||
TEST_CONNECTION,
|
||||
BROWSE_METADATA,
|
||||
READ_QUERY,
|
||||
WRITE_MUTATION,
|
||||
EXPORT,
|
||||
MATERIALIZE
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package tech.easyflow.datacenter.meta.enums;
|
||||
|
||||
public enum DatacenterConnectionErrorCode {
|
||||
INVALID_ARGUMENT,
|
||||
DRIVER_NOT_FOUND,
|
||||
NETWORK_UNREACHABLE,
|
||||
AUTH_FAILED,
|
||||
DATABASE_NOT_FOUND,
|
||||
SCHEMA_NOT_FOUND,
|
||||
PERMISSION_DENIED,
|
||||
UNKNOWN_ERROR
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package tech.easyflow.datacenter.meta.enums;
|
||||
|
||||
public enum DatacenterImportStatus {
|
||||
PENDING,
|
||||
RUNNING,
|
||||
SUCCESS,
|
||||
FAILED,
|
||||
NOT_IMPLEMENTED
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package tech.easyflow.datacenter.meta.enums;
|
||||
|
||||
public enum DatacenterSourceType {
|
||||
PROJECT_MYSQL,
|
||||
EXCEL,
|
||||
EXCEL_MATERIALIZED,
|
||||
MYSQL,
|
||||
POSTGRESQL,
|
||||
ORACLE,
|
||||
GAUSSDB_NATIVE,
|
||||
GBASE_8A,
|
||||
GBASE_8S
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package tech.easyflow.datacenter.meta.enums;
|
||||
|
||||
public enum DatacenterTableKind {
|
||||
PROJECT_MANAGED,
|
||||
EXTERNAL_TABLE,
|
||||
EXTERNAL_VIEW,
|
||||
EXCEL_SHEET,
|
||||
EXCEL_MATERIALIZED,
|
||||
DERIVED_TABLE
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package tech.easyflow.datacenter.meta.model;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DatacenterBatchRegisterRequest {
|
||||
|
||||
private BigInteger sourceId;
|
||||
private String catalogName;
|
||||
private List<String> tableNames = new ArrayList<>();
|
||||
|
||||
public BigInteger getSourceId() {
|
||||
return sourceId;
|
||||
}
|
||||
|
||||
public void setSourceId(BigInteger sourceId) {
|
||||
this.sourceId = sourceId;
|
||||
}
|
||||
|
||||
public String getCatalogName() {
|
||||
return catalogName;
|
||||
}
|
||||
|
||||
public void setCatalogName(String catalogName) {
|
||||
this.catalogName = catalogName;
|
||||
}
|
||||
|
||||
public List<String> getTableNames() {
|
||||
return tableNames;
|
||||
}
|
||||
|
||||
public void setTableNames(List<String> tableNames) {
|
||||
this.tableNames = tableNames;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package tech.easyflow.datacenter.meta.model;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DatacenterBatchRemoveRequest {
|
||||
|
||||
private List<BigInteger> tableIds = new ArrayList<>();
|
||||
|
||||
public List<BigInteger> getTableIds() {
|
||||
return tableIds;
|
||||
}
|
||||
|
||||
public void setTableIds(List<BigInteger> tableIds) {
|
||||
this.tableIds = tableIds;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package tech.easyflow.datacenter.meta.model;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class DatacenterCatalogMeta {
|
||||
private BigInteger id;
|
||||
private BigInteger sourceId;
|
||||
private String catalogName;
|
||||
private String catalogType;
|
||||
private String catalogDesc;
|
||||
|
||||
public BigInteger getId() { return id; }
|
||||
public void setId(BigInteger id) { this.id = id; }
|
||||
public BigInteger getSourceId() { return sourceId; }
|
||||
public void setSourceId(BigInteger sourceId) { this.sourceId = sourceId; }
|
||||
public String getCatalogName() { return catalogName; }
|
||||
public void setCatalogName(String catalogName) { this.catalogName = catalogName; }
|
||||
public String getCatalogType() { return catalogType; }
|
||||
public void setCatalogType(String catalogType) { this.catalogType = catalogType; }
|
||||
public String getCatalogDesc() { return catalogDesc; }
|
||||
public void setCatalogDesc(String catalogDesc) { this.catalogDesc = catalogDesc; }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package tech.easyflow.datacenter.meta.model;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class DatacenterFieldDescriptionUpdate {
|
||||
|
||||
private BigInteger fieldId;
|
||||
private String fieldDesc;
|
||||
|
||||
public BigInteger getFieldId() {
|
||||
return fieldId;
|
||||
}
|
||||
|
||||
public void setFieldId(BigInteger fieldId) {
|
||||
this.fieldId = fieldId;
|
||||
}
|
||||
|
||||
public String getFieldDesc() {
|
||||
return fieldDesc;
|
||||
}
|
||||
|
||||
public void setFieldDesc(String fieldDesc) {
|
||||
this.fieldDesc = fieldDesc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package tech.easyflow.datacenter.meta.model;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class DatacenterRemoveSourceRequest {
|
||||
|
||||
private BigInteger sourceId;
|
||||
|
||||
public BigInteger getSourceId() {
|
||||
return sourceId;
|
||||
}
|
||||
|
||||
public void setSourceId(BigInteger sourceId) {
|
||||
this.sourceId = sourceId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package tech.easyflow.datacenter.meta.model;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DatacenterSaveDescriptionsRequest {
|
||||
|
||||
private BigInteger tableId;
|
||||
private String tableDesc;
|
||||
private List<DatacenterFieldDescriptionUpdate> fields = new ArrayList<>();
|
||||
|
||||
public BigInteger getTableId() {
|
||||
return tableId;
|
||||
}
|
||||
|
||||
public void setTableId(BigInteger tableId) {
|
||||
this.tableId = tableId;
|
||||
}
|
||||
|
||||
public String getTableDesc() {
|
||||
return tableDesc;
|
||||
}
|
||||
|
||||
public void setTableDesc(String tableDesc) {
|
||||
this.tableDesc = tableDesc;
|
||||
}
|
||||
|
||||
public List<DatacenterFieldDescriptionUpdate> getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
public void setFields(List<DatacenterFieldDescriptionUpdate> fields) {
|
||||
this.fields = fields;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package tech.easyflow.datacenter.meta.model;
|
||||
|
||||
import tech.easyflow.datacenter.entity.DatacenterTable;
|
||||
import tech.easyflow.datacenter.entity.DatacenterTableField;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DatacenterTableDetailMeta {
|
||||
private DatacenterTable table;
|
||||
private List<DatacenterTableField> fields = new ArrayList<>();
|
||||
|
||||
public DatacenterTable getTable() { return table; }
|
||||
public void setTable(DatacenterTable table) { this.table = table; }
|
||||
public List<DatacenterTableField> getFields() { return fields; }
|
||||
public void setFields(List<DatacenterTableField> fields) { this.fields = fields; }
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package tech.easyflow.datacenter.meta.service;
|
||||
|
||||
import tech.easyflow.common.entity.LoginAccount;
|
||||
import tech.easyflow.datacenter.entity.DatacenterTable;
|
||||
import tech.easyflow.datacenter.entity.DatacenterTableField;
|
||||
import tech.easyflow.datacenter.execution.model.DatasetRef;
|
||||
import tech.easyflow.datacenter.meta.entity.DatacenterCatalog;
|
||||
import tech.easyflow.datacenter.meta.entity.DatacenterSource;
|
||||
import tech.easyflow.datacenter.meta.model.DatacenterFieldDescriptionUpdate;
|
||||
import tech.easyflow.datacenter.meta.enums.DatacenterSourceType;
|
||||
import tech.easyflow.datacenter.meta.model.DatacenterTableDetailMeta;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
public interface DatacenterDatasetRegistryService {
|
||||
DatacenterSource ensureBuiltinSource(DatacenterSourceType sourceType, LoginAccount account);
|
||||
|
||||
DatacenterCatalog ensureCatalog(DatacenterSource source, String catalogName, LoginAccount account);
|
||||
|
||||
DatacenterTable registerTable(DatacenterSource source, DatacenterCatalog catalog, DatacenterTableDetailMeta detail, LoginAccount account);
|
||||
|
||||
DatacenterTable getTableWithFields(BigInteger tableId);
|
||||
|
||||
List<DatacenterTableField> getFields(BigInteger tableId);
|
||||
|
||||
DatasetRef resolveDatasetRef(BigInteger tableId);
|
||||
|
||||
DatacenterSource getSourceRequired(BigInteger sourceId);
|
||||
|
||||
DatacenterCatalog getCatalogById(BigInteger catalogId);
|
||||
|
||||
List<DatacenterTable> listManagedTables(BigInteger sourceId, BigInteger catalogId);
|
||||
|
||||
int removeTables(List<BigInteger> tableIds);
|
||||
|
||||
DatacenterTable saveDescriptions(BigInteger tableId, String tableDesc, List<DatacenterFieldDescriptionUpdate> fields, LoginAccount account);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package tech.easyflow.datacenter.meta.service;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public final class DatacenterMetaConstants {
|
||||
|
||||
private DatacenterMetaConstants() {
|
||||
}
|
||||
|
||||
public static final BigInteger PROJECT_SOURCE_BASE = new BigInteger("9000000000002000000");
|
||||
public static final BigInteger PROJECT_CATALOG_BASE = new BigInteger("9000000000003000000");
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package tech.easyflow.datacenter.meta.service;
|
||||
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
import tech.easyflow.common.entity.LoginAccount;
|
||||
import tech.easyflow.datacenter.entity.DatacenterTable;
|
||||
import tech.easyflow.datacenter.execution.model.DatacenterConnectionTestResult;
|
||||
import tech.easyflow.datacenter.meta.entity.DatacenterSource;
|
||||
import tech.easyflow.datacenter.meta.model.DatacenterBatchRegisterRequest;
|
||||
import tech.easyflow.datacenter.meta.model.DatacenterCatalogMeta;
|
||||
import tech.easyflow.datacenter.meta.model.DatacenterTableDetailMeta;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
public interface DatacenterSourceService extends IService<DatacenterSource> {
|
||||
DatacenterSource saveSource(DatacenterSource source, LoginAccount account);
|
||||
|
||||
Page<DatacenterSource> pageSources(Long pageNumber, Long pageSize, LoginAccount account);
|
||||
|
||||
DatacenterConnectionTestResult testConnection(DatacenterSource source, LoginAccount account);
|
||||
|
||||
List<DatacenterCatalogMeta> listCatalogs(BigInteger sourceId, LoginAccount account);
|
||||
|
||||
List<DatacenterTable> listTables(BigInteger sourceId, String catalogName, LoginAccount account);
|
||||
|
||||
DatacenterTableDetailMeta getTableDetail(BigInteger sourceId, String catalogName, String tableName, boolean register, LoginAccount account);
|
||||
|
||||
List<DatacenterTable> batchRegisterTables(DatacenterBatchRegisterRequest request, LoginAccount account);
|
||||
|
||||
void removeSource(BigInteger sourceId, LoginAccount account);
|
||||
}
|
||||
@@ -0,0 +1,405 @@
|
||||
package tech.easyflow.datacenter.meta.service.impl;
|
||||
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tech.easyflow.common.entity.LoginAccount;
|
||||
import tech.easyflow.common.web.exceptions.BusinessException;
|
||||
import tech.easyflow.datacenter.adapter.DbHandleManager;
|
||||
import tech.easyflow.datacenter.entity.DatacenterTable;
|
||||
import tech.easyflow.datacenter.entity.DatacenterTableField;
|
||||
import tech.easyflow.datacenter.execution.model.DatasetRef;
|
||||
import tech.easyflow.datacenter.mapper.DatacenterCatalogMapper;
|
||||
import tech.easyflow.datacenter.mapper.DatacenterDatasetVersionMapper;
|
||||
import tech.easyflow.datacenter.mapper.DatacenterDerivedTableMapper;
|
||||
import tech.easyflow.datacenter.mapper.DatacenterImportJobMapper;
|
||||
import tech.easyflow.datacenter.mapper.DatacenterSourceMapper;
|
||||
import tech.easyflow.datacenter.mapper.DatacenterTableFieldMapper;
|
||||
import tech.easyflow.datacenter.mapper.DatacenterTableMapper;
|
||||
import tech.easyflow.datacenter.meta.entity.DatacenterCatalog;
|
||||
import tech.easyflow.datacenter.meta.entity.DatacenterSource;
|
||||
import tech.easyflow.datacenter.meta.model.DatacenterFieldDescriptionUpdate;
|
||||
import tech.easyflow.datacenter.meta.enums.DatacenterSourceType;
|
||||
import tech.easyflow.datacenter.meta.service.DatacenterDatasetRegistryService;
|
||||
import tech.easyflow.datacenter.meta.service.DatacenterMetaConstants;
|
||||
import tech.easyflow.datacenter.meta.model.DatacenterTableDetailMeta;
|
||||
import tech.easyflow.datacenter.meta.enums.DatacenterTableKind;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class DatacenterDatasetRegistryServiceImpl implements DatacenterDatasetRegistryService {
|
||||
|
||||
@Resource
|
||||
private DatacenterSourceMapper sourceMapper;
|
||||
@Resource
|
||||
private DatacenterCatalogMapper catalogMapper;
|
||||
@Resource
|
||||
private DatacenterTableMapper tableMapper;
|
||||
@Resource
|
||||
private DatacenterTableFieldMapper tableFieldMapper;
|
||||
@Resource
|
||||
private DatacenterDatasetVersionMapper datasetVersionMapper;
|
||||
@Resource
|
||||
private DatacenterDerivedTableMapper derivedTableMapper;
|
||||
@Resource
|
||||
private DatacenterImportJobMapper importJobMapper;
|
||||
@Resource
|
||||
private DbHandleManager dbHandleManager;
|
||||
|
||||
@Override
|
||||
public DatacenterSource ensureBuiltinSource(DatacenterSourceType sourceType, LoginAccount account) {
|
||||
BigInteger tenantId = account == null || account.getTenantId() == null ? BigInteger.ZERO : account.getTenantId();
|
||||
BigInteger deptId = account == null || account.getDeptId() == null ? BigInteger.ZERO : account.getDeptId();
|
||||
BigInteger id = builtinSourceId(sourceType, tenantId);
|
||||
DatacenterSource source = sourceMapper.selectOneById(id);
|
||||
if (source != null) {
|
||||
return source;
|
||||
}
|
||||
source = new DatacenterSource();
|
||||
source.setId(id);
|
||||
source.setTenantId(tenantId);
|
||||
source.setDeptId(deptId);
|
||||
source.setSourceType(sourceType.name());
|
||||
source.setBuiltinFlag(1);
|
||||
source.setStatus(0);
|
||||
source.setCreated(new Date());
|
||||
source.setModified(new Date());
|
||||
source.setCreatedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
source.setModifiedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
source.setCapabilitiesJson(Map.of("capabilities", builtinCapabilities(sourceType)));
|
||||
if (sourceType == DatacenterSourceType.PROJECT_MYSQL) {
|
||||
source.setSourceName("项目 MySQL");
|
||||
source.setSourceCode("PROJECT_MYSQL_" + tenantId);
|
||||
source.setAccessMode("READ_WRITE");
|
||||
} else {
|
||||
throw new BusinessException("不支持的内置数据源类型: " + sourceType);
|
||||
}
|
||||
sourceMapper.insert(source);
|
||||
ensureCatalog(source, defaultCatalogName(sourceType), account);
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatacenterCatalog ensureCatalog(DatacenterSource source, String catalogName, LoginAccount account) {
|
||||
QueryWrapper wrapper = QueryWrapper.create();
|
||||
wrapper.eq(DatacenterCatalog::getSourceId, source.getId());
|
||||
wrapper.eq(DatacenterCatalog::getCatalogName, catalogName);
|
||||
DatacenterCatalog catalog = catalogMapper.selectOneByQuery(wrapper);
|
||||
if (catalog != null) {
|
||||
return catalog;
|
||||
}
|
||||
catalog = new DatacenterCatalog();
|
||||
BigInteger catalogId = builtinCatalogId(source, catalogName);
|
||||
if (catalogId != null) {
|
||||
catalog.setId(catalogId);
|
||||
}
|
||||
catalog.setSourceId(source.getId());
|
||||
catalog.setTenantId(source.getTenantId());
|
||||
catalog.setDeptId(source.getDeptId());
|
||||
catalog.setCatalogName(catalogName);
|
||||
catalog.setCatalogDesc(catalogName);
|
||||
catalog.setCatalogType("DATABASE");
|
||||
catalog.setStatus(0);
|
||||
catalog.setCreated(new Date());
|
||||
catalog.setModified(new Date());
|
||||
catalog.setCreatedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
catalog.setModifiedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
catalogMapper.insert(catalog);
|
||||
return catalog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatacenterTable registerTable(DatacenterSource source, DatacenterCatalog catalog, DatacenterTableDetailMeta detail, LoginAccount account) {
|
||||
DatacenterTable table = detail.getTable();
|
||||
applyTableDefaults(table, source, detail);
|
||||
QueryWrapper wrapper = QueryWrapper.create();
|
||||
wrapper.eq(DatacenterTable::getSourceId, source.getId());
|
||||
wrapper.eq(DatacenterTable::getCatalogId, catalog.getId());
|
||||
wrapper.eq(DatacenterTable::getTableName, table.getTableName());
|
||||
DatacenterTable existing = tableMapper.selectOneByQuery(wrapper);
|
||||
Date now = new Date();
|
||||
if (existing == null) {
|
||||
table.setSourceId(source.getId());
|
||||
table.setCatalogId(catalog.getId());
|
||||
table.setTenantId(source.getTenantId());
|
||||
table.setDeptId(source.getDeptId());
|
||||
table.setStatus(0);
|
||||
table.setCreated(now);
|
||||
table.setModified(now);
|
||||
table.setCreatedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
table.setModifiedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
tableMapper.insert(table);
|
||||
} else {
|
||||
if (!hasText(existing.getTableDesc())) {
|
||||
existing.setTableDesc(normalizeDescription(table.getTableDesc()));
|
||||
}
|
||||
existing.setActualTable(table.getActualTable());
|
||||
existing.setMaterializedTable(table.getMaterializedTable());
|
||||
existing.setTableKind(table.getTableKind());
|
||||
existing.setAccessMode(table.getAccessMode());
|
||||
existing.setVersioningEnabled(table.getVersioningEnabled());
|
||||
existing.setCapabilitiesJson(table.getCapabilitiesJson());
|
||||
existing.setModified(now);
|
||||
existing.setModifiedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
tableMapper.update(existing);
|
||||
table = existing;
|
||||
}
|
||||
Map<String, DatacenterTableField> existingFieldMap = getFields(table.getId()).stream()
|
||||
.collect(LinkedHashMap::new, (map, field) -> map.put(field.getFieldName(), field), Map::putAll);
|
||||
QueryWrapper deleteWrapper = QueryWrapper.create();
|
||||
deleteWrapper.eq(DatacenterTableField::getTableId, table.getId());
|
||||
tableFieldMapper.deleteByQuery(deleteWrapper);
|
||||
for (DatacenterTableField field : detail.getFields()) {
|
||||
DatacenterTableField existingField = existingFieldMap.get(field.getFieldName());
|
||||
if (existingField != null && hasText(existingField.getFieldDesc())) {
|
||||
field.setFieldDesc(existingField.getFieldDesc());
|
||||
} else {
|
||||
field.setFieldDesc(normalizeDescription(field.getFieldDesc()));
|
||||
}
|
||||
field.setId(null);
|
||||
field.setTableId(table.getId());
|
||||
field.setCreated(now);
|
||||
field.setModified(now);
|
||||
field.setCreatedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
field.setModifiedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
tableFieldMapper.insert(field);
|
||||
}
|
||||
table.setFields(getFields(table.getId()));
|
||||
return table;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public DatacenterTable saveDescriptions(BigInteger tableId, String tableDesc, List<DatacenterFieldDescriptionUpdate> fields, LoginAccount account) {
|
||||
if (tableId == null) {
|
||||
throw new BusinessException("缺少表 ID");
|
||||
}
|
||||
DatacenterTable table = getTableWithFields(tableId);
|
||||
Date now = new Date();
|
||||
table.setTableDesc(normalizeDescription(tableDesc));
|
||||
table.setModified(now);
|
||||
table.setModifiedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
tableMapper.update(table);
|
||||
|
||||
Map<BigInteger, DatacenterFieldDescriptionUpdate> fieldUpdateMap = new LinkedHashMap<>();
|
||||
if (fields != null) {
|
||||
for (DatacenterFieldDescriptionUpdate field : fields) {
|
||||
if (field == null || field.getFieldId() == null) {
|
||||
continue;
|
||||
}
|
||||
fieldUpdateMap.put(field.getFieldId(), field);
|
||||
}
|
||||
}
|
||||
for (DatacenterTableField field : table.getFields()) {
|
||||
DatacenterFieldDescriptionUpdate update = fieldUpdateMap.get(field.getId());
|
||||
if (update == null) {
|
||||
continue;
|
||||
}
|
||||
field.setFieldDesc(normalizeDescription(update.getFieldDesc()));
|
||||
field.setModified(now);
|
||||
field.setModifiedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
tableFieldMapper.update(field);
|
||||
}
|
||||
return getTableWithFields(tableId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatacenterTable getTableWithFields(BigInteger tableId) {
|
||||
DatacenterTable table = tableMapper.selectOneById(tableId);
|
||||
if (table == null) {
|
||||
throw new BusinessException("数据集不存在: " + tableId);
|
||||
}
|
||||
table.setFields(getFields(tableId));
|
||||
return table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DatacenterTableField> getFields(BigInteger tableId) {
|
||||
QueryWrapper wrapper = QueryWrapper.create();
|
||||
wrapper.eq(DatacenterTableField::getTableId, tableId);
|
||||
wrapper.orderBy("id");
|
||||
return tableFieldMapper.selectListByQuery(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatasetRef resolveDatasetRef(BigInteger tableId) {
|
||||
DatacenterTable table = getTableWithFields(tableId);
|
||||
DatasetRef ref = new DatasetRef();
|
||||
ref.setTableId(tableId);
|
||||
ref.setSourceId(table.getSourceId());
|
||||
ref.setCatalogId(table.getCatalogId());
|
||||
ref.setTableName(table.getTableName());
|
||||
DatacenterCatalog catalog = getCatalogById(table.getCatalogId());
|
||||
if (catalog != null) {
|
||||
ref.setCatalogName(catalog.getCatalogName());
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatacenterSource getSourceRequired(BigInteger sourceId) {
|
||||
DatacenterSource source = sourceMapper.selectOneById(sourceId);
|
||||
if (source == null) {
|
||||
throw new BusinessException("连接不存在");
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatacenterCatalog getCatalogById(BigInteger catalogId) {
|
||||
if (catalogId == null) {
|
||||
return null;
|
||||
}
|
||||
return catalogMapper.selectOneById(catalogId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DatacenterTable> listManagedTables(BigInteger sourceId, BigInteger catalogId) {
|
||||
QueryWrapper wrapper = QueryWrapper.create();
|
||||
wrapper.eq(DatacenterTable::getSourceId, sourceId);
|
||||
if (catalogId != null) {
|
||||
wrapper.eq(DatacenterTable::getCatalogId, catalogId);
|
||||
}
|
||||
wrapper.orderBy("created desc");
|
||||
return tableMapper.selectListByQuery(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int removeTables(List<BigInteger> tableIds) {
|
||||
List<BigInteger> ids = tableIds == null ? List.of() : tableIds.stream().filter(id -> id != null).distinct().toList();
|
||||
if (ids.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
QueryWrapper physicalTableWrapper = QueryWrapper.create();
|
||||
physicalTableWrapper.in(DatacenterTable::getId, ids);
|
||||
List<DatacenterTable> tables = tableMapper.selectListByQuery(physicalTableWrapper);
|
||||
tables.forEach(this::deletePhysicalTableIfNecessary);
|
||||
|
||||
QueryWrapper fieldWrapper = QueryWrapper.create();
|
||||
fieldWrapper.in(DatacenterTableField::getTableId, ids);
|
||||
tableFieldMapper.deleteByQuery(fieldWrapper);
|
||||
|
||||
QueryWrapper versionWrapper = QueryWrapper.create();
|
||||
versionWrapper.in(tech.easyflow.datacenter.meta.entity.DatacenterDatasetVersion::getTableId, ids);
|
||||
datasetVersionMapper.deleteByQuery(versionWrapper);
|
||||
|
||||
QueryWrapper importJobWrapper = QueryWrapper.create();
|
||||
importJobWrapper.in(tech.easyflow.datacenter.meta.entity.DatacenterImportJob::getTableId, ids);
|
||||
importJobMapper.deleteByQuery(importJobWrapper);
|
||||
|
||||
QueryWrapper upstreamWrapper = QueryWrapper.create();
|
||||
upstreamWrapper.in(tech.easyflow.datacenter.meta.entity.DatacenterDerivedTable::getSourceTableId, ids);
|
||||
derivedTableMapper.deleteByQuery(upstreamWrapper);
|
||||
|
||||
QueryWrapper downstreamWrapper = QueryWrapper.create();
|
||||
downstreamWrapper.in(tech.easyflow.datacenter.meta.entity.DatacenterDerivedTable::getDerivedTableId, ids);
|
||||
derivedTableMapper.deleteByQuery(downstreamWrapper);
|
||||
|
||||
QueryWrapper tableWrapper = QueryWrapper.create();
|
||||
tableWrapper.in(DatacenterTable::getId, ids);
|
||||
return tableMapper.deleteByQuery(tableWrapper);
|
||||
}
|
||||
|
||||
private void deletePhysicalTableIfNecessary(DatacenterTable table) {
|
||||
if (table == null || !shouldDropPhysicalTable(table)) {
|
||||
return;
|
||||
}
|
||||
String physicalTableName = table.getActualTable();
|
||||
if (physicalTableName == null || physicalTableName.isBlank()) {
|
||||
physicalTableName = table.getMaterializedTable();
|
||||
}
|
||||
if (physicalTableName == null || physicalTableName.isBlank()) {
|
||||
return;
|
||||
}
|
||||
DatacenterTable physicalTable = new DatacenterTable();
|
||||
physicalTable.setActualTable(physicalTableName);
|
||||
dbHandleManager.getDbHandler().deleteTable(physicalTable);
|
||||
}
|
||||
|
||||
private boolean shouldDropPhysicalTable(DatacenterTable table) {
|
||||
String tableKind = table.getTableKind();
|
||||
if (tableKind == null || tableKind.isBlank()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
DatacenterTableKind kind = DatacenterTableKind.valueOf(tableKind);
|
||||
return kind == DatacenterTableKind.PROJECT_MANAGED
|
||||
|| kind == DatacenterTableKind.EXCEL_SHEET
|
||||
|| kind == DatacenterTableKind.EXCEL_MATERIALIZED
|
||||
|| kind == DatacenterTableKind.DERIVED_TABLE;
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void applyTableDefaults(DatacenterTable table, DatacenterSource source, DatacenterTableDetailMeta detail) {
|
||||
if (table.getTableKind() == null || table.getTableKind().isBlank()) {
|
||||
table.setTableKind(DatacenterTableKind.EXTERNAL_TABLE.name());
|
||||
}
|
||||
if (table.getAccessMode() == null || table.getAccessMode().isBlank()) {
|
||||
table.setAccessMode("READ_ONLY");
|
||||
}
|
||||
if (table.getVersioningEnabled() == null) {
|
||||
table.setVersioningEnabled(0);
|
||||
}
|
||||
if (table.getCapabilitiesJson() == null || table.getCapabilitiesJson().isEmpty()) {
|
||||
table.setCapabilitiesJson(Map.of(
|
||||
"capabilities",
|
||||
source.getCapabilitiesJson() == null
|
||||
? List.of()
|
||||
: source.getCapabilitiesJson().getOrDefault("capabilities", List.of())
|
||||
));
|
||||
}
|
||||
if ((table.getActualTable() == null || table.getActualTable().isBlank()) && table.getTableName() != null) {
|
||||
table.setActualTable(table.getTableName());
|
||||
}
|
||||
table.setTableDesc(normalizeDescription(table.getTableDesc()));
|
||||
if (detail.getFields() == null) {
|
||||
detail.setFields(List.of());
|
||||
}
|
||||
}
|
||||
|
||||
private String normalizeDescription(String description) {
|
||||
if (description == null) {
|
||||
return "";
|
||||
}
|
||||
return description.trim();
|
||||
}
|
||||
|
||||
private boolean hasText(String value) {
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
|
||||
private BigInteger builtinSourceId(DatacenterSourceType sourceType, BigInteger tenantId) {
|
||||
if (sourceType == DatacenterSourceType.PROJECT_MYSQL) {
|
||||
return DatacenterMetaConstants.PROJECT_SOURCE_BASE.add(tenantId);
|
||||
}
|
||||
throw new BusinessException("不支持的内置源 ID 计算");
|
||||
}
|
||||
|
||||
private BigInteger builtinCatalogId(DatacenterSource source, String catalogName) {
|
||||
if (source.getId().compareTo(DatacenterMetaConstants.PROJECT_SOURCE_BASE) >= 0
|
||||
&& defaultCatalogName(DatacenterSourceType.PROJECT_MYSQL).equals(catalogName)) {
|
||||
return DatacenterMetaConstants.PROJECT_CATALOG_BASE.add(source.getTenantId());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String defaultCatalogName(DatacenterSourceType sourceType) {
|
||||
if (sourceType == DatacenterSourceType.PROJECT_MYSQL) {
|
||||
return "project_mysql";
|
||||
}
|
||||
return sourceType.name().toLowerCase();
|
||||
}
|
||||
|
||||
private List<String> builtinCapabilities(DatacenterSourceType sourceType) {
|
||||
return List.of("TEST_CONNECTION", "BROWSE_METADATA", "READ_QUERY", "WRITE_MUTATION");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
package tech.easyflow.datacenter.meta.service.impl;
|
||||
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tech.easyflow.common.entity.LoginAccount;
|
||||
import tech.easyflow.common.web.exceptions.BusinessException;
|
||||
import tech.easyflow.datacenter.connector.DatacenterConnector;
|
||||
import tech.easyflow.datacenter.connector.DatacenterConnectorRegistry;
|
||||
import tech.easyflow.datacenter.entity.DatacenterTable;
|
||||
import tech.easyflow.datacenter.mapper.DatacenterCatalogMapper;
|
||||
import tech.easyflow.datacenter.mapper.DatacenterSourceMapper;
|
||||
import tech.easyflow.datacenter.meta.entity.DatacenterCatalog;
|
||||
import tech.easyflow.datacenter.meta.entity.DatacenterSource;
|
||||
import tech.easyflow.datacenter.meta.enums.DatacenterSourceType;
|
||||
import tech.easyflow.datacenter.meta.model.DatacenterBatchRegisterRequest;
|
||||
import tech.easyflow.datacenter.meta.model.DatacenterCatalogMeta;
|
||||
import tech.easyflow.datacenter.meta.model.DatacenterTableDetailMeta;
|
||||
import tech.easyflow.datacenter.meta.service.DatacenterDatasetRegistryService;
|
||||
import tech.easyflow.datacenter.meta.service.DatacenterSourceService;
|
||||
import tech.easyflow.datacenter.meta.support.DatacenterSourceConnectionDefaults;
|
||||
import tech.easyflow.datacenter.execution.model.DatacenterConnectionTestResult;
|
||||
import tech.easyflow.datacenter.security.DatacenterCredentialCipher;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class DatacenterSourceServiceImpl extends ServiceImpl<DatacenterSourceMapper, DatacenterSource> implements DatacenterSourceService {
|
||||
|
||||
@Resource
|
||||
private DatacenterConnectorRegistry connectorRegistry;
|
||||
@Resource
|
||||
private DatacenterDatasetRegistryService registryService;
|
||||
@Resource
|
||||
private DatacenterCredentialCipher credentialCipher;
|
||||
@Resource
|
||||
private DatacenterCatalogMapper catalogMapper;
|
||||
@Resource
|
||||
private DatacenterSourceConnectionDefaults connectionDefaults;
|
||||
|
||||
@Override
|
||||
public DatacenterSource saveSource(DatacenterSource source, LoginAccount account) {
|
||||
if (source == null || source.getSourceType() == null || source.getSourceType().isBlank()) {
|
||||
throw new BusinessException("数据源类型不能为空");
|
||||
}
|
||||
DatacenterSource existing = source.getId() == null ? null : getById(source.getId());
|
||||
DatacenterSource normalized = mergeWithExisting(existing, source);
|
||||
DatacenterConnector connector = connectorRegistry.getConnector(normalized.getSourceType());
|
||||
applyCredentialCipher(normalized, existing);
|
||||
normalized.setConfigJson(connectionDefaults.sanitizeConfig(normalized.getConfigJson()));
|
||||
connectionDefaults.normalize(normalized);
|
||||
normalized.setCapabilitiesJson(Map.of("capabilities", connector.getCapabilities().stream().map(Enum::name).toList()));
|
||||
Date now = new Date();
|
||||
if (normalized.getId() == null) {
|
||||
normalized.setCreated(now);
|
||||
normalized.setCreatedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
normalized.setTenantId(account == null ? BigInteger.ZERO : account.getTenantId());
|
||||
normalized.setDeptId(account == null ? BigInteger.ZERO : account.getDeptId());
|
||||
normalized.setStatus(normalized.getStatus() == null ? 0 : normalized.getStatus());
|
||||
normalized.setModified(now);
|
||||
normalized.setModifiedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
save(normalized);
|
||||
} else {
|
||||
if (existing == null) {
|
||||
throw new BusinessException("连接不存在");
|
||||
}
|
||||
normalized.setModified(now);
|
||||
normalized.setModifiedBy(account == null ? BigInteger.ZERO : account.getId());
|
||||
updateById(normalized);
|
||||
}
|
||||
return getById(normalized.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DatacenterSource> pageSources(Long pageNumber, Long pageSize, LoginAccount account) {
|
||||
registryService.ensureBuiltinSource(DatacenterSourceType.PROJECT_MYSQL, account);
|
||||
return page(new Page<>(pageNumber == null ? 1L : pageNumber, pageSize == null ? 10L : pageSize), QueryWrapper.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatacenterConnectionTestResult testConnection(DatacenterSource source, LoginAccount account) {
|
||||
DatacenterSource existing = source != null && source.getId() != null ? getById(source.getId()) : null;
|
||||
if (source != null && source.getId() != null && existing == null) {
|
||||
throw new BusinessException("连接不存在");
|
||||
}
|
||||
DatacenterSource actual = mergeWithExisting(existing, source);
|
||||
if (DatacenterSourceType.PROJECT_MYSQL.name().equals(actual.getSourceType())) {
|
||||
actual = registryService.ensureBuiltinSource(DatacenterSourceType.PROJECT_MYSQL, account);
|
||||
}
|
||||
applyCredentialCipher(actual, existing);
|
||||
actual.setConfigJson(connectionDefaults.sanitizeConfig(actual.getConfigJson()));
|
||||
connectionDefaults.normalize(actual);
|
||||
DatacenterConnector connector = connectorRegistry.getConnector(actual.getSourceType());
|
||||
DatacenterConnectionTestResult result = connector.testConnection(actual);
|
||||
Map<String, Object> details = new LinkedHashMap<>();
|
||||
if (result.getDetails() != null) {
|
||||
details.putAll(result.getDetails());
|
||||
}
|
||||
details.put("effectiveDriverClassName", actual.getDriverClassName());
|
||||
details.put("effectiveJdbcUrl", actual.getJdbcUrl());
|
||||
details.put("effectivePort", actual.getPort());
|
||||
result.setDetails(details);
|
||||
if (actual.getId() != null) {
|
||||
DatacenterSource persisted = new DatacenterSource();
|
||||
persisted.setId(actual.getId());
|
||||
persisted.setLastTestStatus(result.isSuccess() ? "SUCCESS" : "FAILED");
|
||||
persisted.setLastTestMessage(result.getMessage());
|
||||
persisted.setLastTestedAt(new Date());
|
||||
updateById(persisted);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DatacenterCatalogMeta> listCatalogs(BigInteger sourceId, LoginAccount account) {
|
||||
DatacenterSource source = registryService.getSourceRequired(sourceId);
|
||||
if (isManagedOnly(source.getSourceType())) {
|
||||
QueryWrapper wrapper = QueryWrapper.create();
|
||||
wrapper.eq(DatacenterCatalog::getSourceId, sourceId);
|
||||
return catalogMapper.selectListByQuery(wrapper).stream().map(this::toCatalogMeta).collect(Collectors.toList());
|
||||
}
|
||||
return connectorRegistry.getConnector(source.getSourceType()).listCatalogs(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DatacenterTable> listTables(BigInteger sourceId, String catalogName, LoginAccount account) {
|
||||
DatacenterSource source = registryService.getSourceRequired(sourceId);
|
||||
if (isManagedOnly(source.getSourceType())) {
|
||||
BigInteger catalogId = resolveCatalogId(sourceId, catalogName);
|
||||
return registryService.listManagedTables(sourceId, catalogId);
|
||||
}
|
||||
return connectorRegistry.getConnector(source.getSourceType()).listTables(source, catalogName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatacenterTableDetailMeta getTableDetail(BigInteger sourceId, String catalogName, String tableName, boolean register, LoginAccount account) {
|
||||
DatacenterSource source = registryService.getSourceRequired(sourceId);
|
||||
if (isManagedOnly(source.getSourceType())) {
|
||||
BigInteger catalogId = resolveCatalogId(sourceId, catalogName);
|
||||
List<DatacenterTable> tables = registryService.listManagedTables(sourceId, catalogId);
|
||||
DatacenterTable target = tables.stream().filter(item -> tableName.equals(item.getTableName())).findFirst()
|
||||
.orElseThrow(() -> new BusinessException("数据集不存在: " + tableName));
|
||||
DatacenterTableDetailMeta detail = new DatacenterTableDetailMeta();
|
||||
detail.setTable(registryService.getTableWithFields(target.getId()));
|
||||
detail.setFields(detail.getTable().getFields());
|
||||
return detail;
|
||||
}
|
||||
DatacenterConnector connector = connectorRegistry.getConnector(source.getSourceType());
|
||||
DatacenterTableDetailMeta detail = connector.getTableDetail(source, catalogName, tableName);
|
||||
if (register) {
|
||||
DatacenterCatalog catalog = registryService.ensureCatalog(source, catalogName, account);
|
||||
DatacenterTable table = registryService.registerTable(source, catalog, detail, account);
|
||||
detail.setTable(table);
|
||||
detail.setFields(table.getFields());
|
||||
}
|
||||
return detail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DatacenterTable> batchRegisterTables(DatacenterBatchRegisterRequest request, LoginAccount account) {
|
||||
if (request == null || request.getSourceId() == null) {
|
||||
throw new BusinessException("数据连接不能为空");
|
||||
}
|
||||
if (request.getCatalogName() == null || request.getCatalogName().isBlank()) {
|
||||
throw new BusinessException("库不能为空");
|
||||
}
|
||||
List<String> tableNames = request.getTableNames() == null
|
||||
? List.of()
|
||||
: request.getTableNames().stream().filter(name -> name != null && !name.isBlank()).distinct().toList();
|
||||
if (tableNames.isEmpty()) {
|
||||
throw new BusinessException("至少选择一张表");
|
||||
}
|
||||
DatacenterSource source = registryService.getSourceRequired(request.getSourceId());
|
||||
if (isManagedOnly(source.getSourceType())) {
|
||||
throw new BusinessException("当前数据连接不支持批量接入");
|
||||
}
|
||||
DatacenterConnector connector = connectorRegistry.getConnector(source.getSourceType());
|
||||
DatacenterCatalog catalog = registryService.ensureCatalog(source, request.getCatalogName(), account);
|
||||
return tableNames.stream().map(tableName -> {
|
||||
DatacenterTableDetailMeta detail = connector.getTableDetail(source, request.getCatalogName(), tableName);
|
||||
return registryService.registerTable(source, catalog, detail, account);
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void removeSource(BigInteger sourceId, LoginAccount account) {
|
||||
if (sourceId == null) {
|
||||
throw new BusinessException("数据连接不能为空");
|
||||
}
|
||||
DatacenterSource source = getById(sourceId);
|
||||
if (source == null) {
|
||||
throw new BusinessException("连接不存在");
|
||||
}
|
||||
if (Boolean.TRUE.equals(source.getBuiltinFlag())) {
|
||||
throw new BusinessException("内置数据连接不支持删除");
|
||||
}
|
||||
|
||||
List<BigInteger> tableIds = registryService.listManagedTables(sourceId, null).stream()
|
||||
.map(DatacenterTable::getId)
|
||||
.filter(id -> id != null)
|
||||
.toList();
|
||||
registryService.removeTables(tableIds);
|
||||
|
||||
QueryWrapper catalogWrapper = QueryWrapper.create();
|
||||
catalogWrapper.eq(DatacenterCatalog::getSourceId, sourceId);
|
||||
catalogMapper.deleteByQuery(catalogWrapper);
|
||||
|
||||
removeById(sourceId);
|
||||
}
|
||||
|
||||
private boolean isManagedOnly(String sourceType) {
|
||||
return DatacenterSourceType.EXCEL.name().equals(sourceType)
|
||||
|| DatacenterSourceType.EXCEL_MATERIALIZED.name().equals(sourceType);
|
||||
}
|
||||
|
||||
private DatacenterCatalogMeta toCatalogMeta(DatacenterCatalog catalog) {
|
||||
DatacenterCatalogMeta meta = new DatacenterCatalogMeta();
|
||||
meta.setId(catalog.getId());
|
||||
meta.setSourceId(catalog.getSourceId());
|
||||
meta.setCatalogName(catalog.getCatalogName());
|
||||
meta.setCatalogDesc(catalog.getCatalogDesc());
|
||||
meta.setCatalogType(catalog.getCatalogType());
|
||||
return meta;
|
||||
}
|
||||
|
||||
private BigInteger resolveCatalogId(BigInteger sourceId, String catalogName) {
|
||||
if (catalogName == null || catalogName.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
QueryWrapper wrapper = QueryWrapper.create();
|
||||
wrapper.eq(DatacenterCatalog::getSourceId, sourceId);
|
||||
wrapper.eq(DatacenterCatalog::getCatalogName, catalogName);
|
||||
DatacenterCatalog catalog = catalogMapper.selectOneByQuery(wrapper);
|
||||
if (catalog == null) {
|
||||
throw new BusinessException("目录不存在: " + catalogName);
|
||||
}
|
||||
return catalog.getId();
|
||||
}
|
||||
|
||||
private void applyCredentialCipher(DatacenterSource target, DatacenterSource existing) {
|
||||
String password = extractPassword(target.getConfigJson());
|
||||
if (password != null) {
|
||||
target.setCredentialCipher(credentialCipher.encrypt(password));
|
||||
return;
|
||||
}
|
||||
if ((target.getCredentialCipher() == null || target.getCredentialCipher().isBlank()) && existing != null) {
|
||||
target.setCredentialCipher(existing.getCredentialCipher());
|
||||
}
|
||||
}
|
||||
|
||||
private String extractPassword(Map<String, Object> configJson) {
|
||||
if (configJson == null) {
|
||||
return null;
|
||||
}
|
||||
Object password = configJson.get("password");
|
||||
if (password == null) {
|
||||
return null;
|
||||
}
|
||||
String value = String.valueOf(password);
|
||||
return value.isBlank() ? null : value;
|
||||
}
|
||||
|
||||
private DatacenterSource mergeWithExisting(DatacenterSource existing, DatacenterSource incoming) {
|
||||
if (incoming == null) {
|
||||
return existing;
|
||||
}
|
||||
if (existing == null) {
|
||||
return incoming;
|
||||
}
|
||||
DatacenterSource merged = new DatacenterSource();
|
||||
merged.setId(existing.getId());
|
||||
merged.setCreated(existing.getCreated());
|
||||
merged.setCreatedBy(existing.getCreatedBy());
|
||||
merged.setTenantId(existing.getTenantId());
|
||||
merged.setDeptId(existing.getDeptId());
|
||||
merged.setBuiltinFlag(existing.getBuiltinFlag());
|
||||
merged.setStatus(existing.getStatus());
|
||||
merged.setLastTestStatus(existing.getLastTestStatus());
|
||||
merged.setLastTestMessage(existing.getLastTestMessage());
|
||||
merged.setLastTestedAt(existing.getLastTestedAt());
|
||||
merged.setOptions(existing.getOptions());
|
||||
merged.setSourceName(valueOrExisting(incoming.getSourceName(), existing.getSourceName()));
|
||||
merged.setSourceCode(valueOrExisting(incoming.getSourceCode(), existing.getSourceCode()));
|
||||
merged.setSourceType(valueOrExisting(incoming.getSourceType(), existing.getSourceType()));
|
||||
merged.setAccessMode(valueOrExisting(incoming.getAccessMode(), existing.getAccessMode()));
|
||||
merged.setDriverClassName(valueOrExisting(incoming.getDriverClassName(), existing.getDriverClassName()));
|
||||
merged.setJdbcUrl(valueOrExisting(incoming.getJdbcUrl(), existing.getJdbcUrl()));
|
||||
merged.setHost(valueOrExisting(incoming.getHost(), existing.getHost()));
|
||||
merged.setPort(incoming.getPort() != null ? incoming.getPort() : existing.getPort());
|
||||
merged.setDatabaseName(valueOrExisting(incoming.getDatabaseName(), existing.getDatabaseName()));
|
||||
merged.setSchemaName(valueOrExisting(incoming.getSchemaName(), existing.getSchemaName()));
|
||||
merged.setUsername(valueOrExisting(incoming.getUsername(), existing.getUsername()));
|
||||
merged.setCredentialCipher(valueOrExisting(incoming.getCredentialCipher(), existing.getCredentialCipher()));
|
||||
merged.setConfigJson(incoming.getConfigJson() != null ? incoming.getConfigJson() : existing.getConfigJson());
|
||||
merged.setCapabilitiesJson(existing.getCapabilitiesJson());
|
||||
return merged;
|
||||
}
|
||||
|
||||
private String valueOrExisting(String incoming, String existing) {
|
||||
return incoming != null ? incoming : existing;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package tech.easyflow.datacenter.meta.support;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import org.springframework.stereotype.Component;
|
||||
import tech.easyflow.datacenter.meta.entity.DatacenterSource;
|
||||
import tech.easyflow.datacenter.meta.enums.DatacenterSourceType;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class DatacenterSourceConnectionDefaults {
|
||||
|
||||
public boolean supportsExternalConnection(String sourceType) {
|
||||
if (StrUtil.isBlank(sourceType)) {
|
||||
return false;
|
||||
}
|
||||
DatacenterSourceType resolved = resolveSourceType(sourceType);
|
||||
if (resolved == null) {
|
||||
return false;
|
||||
}
|
||||
return switch (resolved) {
|
||||
case MYSQL, POSTGRESQL, ORACLE, GAUSSDB_NATIVE, GBASE_8A, GBASE_8S -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
public DatacenterSource normalize(DatacenterSource source) {
|
||||
if (source == null || !supportsExternalConnection(source.getSourceType())) {
|
||||
return source;
|
||||
}
|
||||
if (source.getPort() == null || source.getPort() <= 0) {
|
||||
source.setPort(defaultPort(source.getSourceType()));
|
||||
}
|
||||
if (StrUtil.isBlank(source.getDriverClassName())) {
|
||||
source.setDriverClassName(defaultDriverClassName(source.getSourceType()));
|
||||
}
|
||||
if (StrUtil.isBlank(source.getJdbcUrl())) {
|
||||
String jdbcUrl = buildJdbcUrl(source);
|
||||
if (StrUtil.isNotBlank(jdbcUrl)) {
|
||||
source.setJdbcUrl(jdbcUrl);
|
||||
}
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
public Map<String, Object> sanitizeConfig(Map<String, Object> configJson) {
|
||||
Map<String, Object> sanitized = new LinkedHashMap<>();
|
||||
if (configJson == null || configJson.isEmpty()) {
|
||||
return sanitized;
|
||||
}
|
||||
sanitized.putAll(configJson);
|
||||
sanitized.remove("password");
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
public Integer defaultPort(String sourceType) {
|
||||
DatacenterSourceType resolved = requireSourceType(sourceType);
|
||||
return switch (resolved) {
|
||||
case MYSQL -> 3306;
|
||||
case POSTGRESQL, GAUSSDB_NATIVE -> 5432;
|
||||
case ORACLE -> 1521;
|
||||
case GBASE_8A -> 5258;
|
||||
case GBASE_8S -> 9088;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
public String defaultDriverClassName(String sourceType) {
|
||||
DatacenterSourceType resolved = requireSourceType(sourceType);
|
||||
return switch (resolved) {
|
||||
case MYSQL -> "com.mysql.cj.jdbc.Driver";
|
||||
case POSTGRESQL, GAUSSDB_NATIVE -> "org.postgresql.Driver";
|
||||
case ORACLE -> "oracle.jdbc.OracleDriver";
|
||||
case GBASE_8A -> "com.gbase.jdbc.Driver";
|
||||
case GBASE_8S -> "com.gbasedbt.jdbc.Driver";
|
||||
default -> "";
|
||||
};
|
||||
}
|
||||
|
||||
public String buildJdbcUrl(DatacenterSource source) {
|
||||
if (source == null || !supportsExternalConnection(source.getSourceType())) {
|
||||
return null;
|
||||
}
|
||||
String host = StrUtil.trimToEmpty(source.getHost());
|
||||
Integer port = source.getPort() == null || source.getPort() <= 0 ? defaultPort(source.getSourceType()) : source.getPort();
|
||||
String databaseName = resolveDatabaseName(source);
|
||||
if (StrUtil.isBlank(host) || port == null || StrUtil.isBlank(databaseName)) {
|
||||
return null;
|
||||
}
|
||||
DatacenterSourceType resolved = requireSourceType(source.getSourceType());
|
||||
return switch (resolved) {
|
||||
case MYSQL -> String.format(
|
||||
"jdbc:mysql://%s:%d/%s?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false",
|
||||
host, port, databaseName
|
||||
);
|
||||
case POSTGRESQL -> String.format("jdbc:postgresql://%s:%d/%s", host, port, databaseName);
|
||||
case ORACLE -> String.format("jdbc:oracle:thin:@//%s:%d/%s", host, port, databaseName);
|
||||
case GAUSSDB_NATIVE -> String.format("jdbc:postgresql://%s:%d/%s", host, port, databaseName);
|
||||
case GBASE_8A -> String.format("jdbc:gbase://%s:%d/%s", host, port, databaseName);
|
||||
case GBASE_8S -> {
|
||||
String informixServer = resolveInformixServer(source);
|
||||
if (StrUtil.isBlank(informixServer)) {
|
||||
yield null;
|
||||
}
|
||||
yield String.format("jdbc:gbasedbt-sqli://%s:%d/%s:INFORMIXSERVER=%s", host, port, databaseName, informixServer);
|
||||
}
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private DatacenterSourceType requireSourceType(String sourceType) {
|
||||
DatacenterSourceType resolved = resolveSourceType(sourceType);
|
||||
if (resolved == null) {
|
||||
throw new IllegalArgumentException("Unsupported datacenter source type: " + sourceType);
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
private DatacenterSourceType resolveSourceType(String sourceType) {
|
||||
try {
|
||||
return DatacenterSourceType.valueOf(sourceType);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveDatabaseName(DatacenterSource source) {
|
||||
if (StrUtil.isNotBlank(source.getDatabaseName())) {
|
||||
return source.getDatabaseName().trim();
|
||||
}
|
||||
if (source.getConfigJson() == null) {
|
||||
return null;
|
||||
}
|
||||
Object serviceName = source.getConfigJson().get("serviceName");
|
||||
if (serviceName != null && StrUtil.isNotBlank(String.valueOf(serviceName))) {
|
||||
return String.valueOf(serviceName).trim();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String resolveInformixServer(DatacenterSource source) {
|
||||
if (source.getConfigJson() == null) {
|
||||
return null;
|
||||
}
|
||||
Object informixServer = source.getConfigJson().get("informixServer");
|
||||
if (informixServer == null) {
|
||||
return null;
|
||||
}
|
||||
String value = String.valueOf(informixServer).trim();
|
||||
return value.isEmpty() ? null : value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user