重构:使用 MyBatis-Flex 迁移应用 ORM

将应用自管表的 JdbcClient 数据访问迁移为实体、Mapper、构造器查询和必要的显式 SQL。

保留 AgentScope 自管表及原有业务语义,并补充事务、查询与数据库集成测试。
This commit is contained in:
Zhu Junhao
2026-08-31 12:13:06 +08:00
parent c13302c0cb
commit e968a8ddc1
54 changed files with 3702 additions and 698 deletions

View File

@@ -0,0 +1,55 @@
package tech.easyflow.manuagent.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.time.OffsetDateTime;
import java.util.UUID;
import org.apache.ibatis.type.JdbcType;
import tech.easyflow.manuagent.typehandler.JsonbStringTypeHandler;
import tech.easyflow.manuagent.typehandler.UuidTypeHandler;
/**
* 映射 {@code app.agent_event} 表的持久化 Agent 事件。
*
* <p>事件 ID 由 PostgreSQL 的 BIGSERIAL 序列生成,业务代码通过
* {@code INSERT ... RETURNING} 原子取得该 ID确保游标回放顺序与数据库提交顺序一致。</p>
*/
@Table(value = "agent_event", schema = "app")
public class AgentEventEntity {
/** PostgreSQL 全局递增事件序号。 */
@Id(keyType = KeyType.Auto)
private Long id;
/** 事件所属项目。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID projectId;
/** 事件所属 Agent Run。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID runId;
/** AG-UI 事件类型。 */
private String eventType;
/** 用于外部追踪和去重的随机事件标识。 */
private String eventId;
/** JSONB 格式的事件负载。 */
@Column(value = "payload", jdbcType = JdbcType.OTHER, typeHandler = JsonbStringTypeHandler.class)
private String payloadJson;
/** 数据库记录的事件创建时间。 */
private OffsetDateTime createdAt;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public UUID getProjectId() { return projectId; }
public void setProjectId(UUID projectId) { this.projectId = projectId; }
public UUID getRunId() { return runId; }
public void setRunId(UUID runId) { this.runId = runId; }
public String getEventType() { return eventType; }
public void setEventType(String eventType) { this.eventType = eventType; }
public String getEventId() { return eventId; }
public void setEventId(String eventId) { this.eventId = eventId; }
public String getPayloadJson() { return payloadJson; }
public void setPayloadJson(String payloadJson) { this.payloadJson = payloadJson; }
public OffsetDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; }
}

View File

@@ -0,0 +1,86 @@
package tech.easyflow.manuagent.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.keygen.KeyGenerators;
import java.time.OffsetDateTime;
import java.util.UUID;
import org.apache.ibatis.type.JdbcType;
import tech.easyflow.manuagent.typehandler.JsonbStringTypeHandler;
import tech.easyflow.manuagent.typehandler.UuidTypeHandler;
/**
* 映射 {@code app.agent_run} 表的 Agent 运行状态实体。
*
* <p>运行终态切换并不依赖 BaseMapper 的无条件更新,而由 Mapper XML 使用
* {@code WHERE status = 'RUNNING'} 实现乐观状态机,避免停止、完成和失败并发覆盖。</p>
*/
@Table(value = "agent_run", schema = "app")
public class AgentRunEntity {
/** Run 主键。 */
@Id(keyType = KeyType.Generator, value = KeyGenerators.uuid)
@Column(typeHandler = UuidTypeHandler.class)
private UUID id;
/** 所属项目。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID projectId;
/** 恢复、重试场景下关联的父 Run。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID parentRunId;
/** 本次 Run 固定使用的模型配置。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID modelConfigId;
/** INITIAL、RESUME 或 RETRY。 */
private String triggerType;
/** 当前运行状态。 */
private String status;
/** 等待用户确认时保存的 Ask JSON。 */
@Column(jdbcType = JdbcType.OTHER, typeHandler = JsonbStringTypeHandler.class)
private String pendingInterrupt;
/** 跨日志追踪标识。 */
private String traceId;
/** 失败或中断错误码。 */
private String errorCode;
/** 面向用户的失败信息。 */
private String errorMessage;
/** Run 开始时间。 */
private OffsetDateTime startedAt;
/** 进入终态或等待态的时间。 */
private OffsetDateTime endedAt;
/** 创建时间。 */
private OffsetDateTime createdAt;
/** 最后更新时间。 */
private OffsetDateTime updatedAt;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public UUID getProjectId() { return projectId; }
public void setProjectId(UUID projectId) { this.projectId = projectId; }
public UUID getParentRunId() { return parentRunId; }
public void setParentRunId(UUID parentRunId) { this.parentRunId = parentRunId; }
public UUID getModelConfigId() { return modelConfigId; }
public void setModelConfigId(UUID modelConfigId) { this.modelConfigId = modelConfigId; }
public String getTriggerType() { return triggerType; }
public void setTriggerType(String triggerType) { this.triggerType = triggerType; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getPendingInterrupt() { return pendingInterrupt; }
public void setPendingInterrupt(String pendingInterrupt) { this.pendingInterrupt = pendingInterrupt; }
public String getTraceId() { return traceId; }
public void setTraceId(String traceId) { this.traceId = traceId; }
public String getErrorCode() { return errorCode; }
public void setErrorCode(String errorCode) { this.errorCode = errorCode; }
public String getErrorMessage() { return errorMessage; }
public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
public OffsetDateTime getStartedAt() { return startedAt; }
public void setStartedAt(OffsetDateTime startedAt) { this.startedAt = startedAt; }
public OffsetDateTime getEndedAt() { return endedAt; }
public void setEndedAt(OffsetDateTime endedAt) { this.endedAt = endedAt; }
public OffsetDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; }
public OffsetDateTime getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; }
}

View File

@@ -0,0 +1,112 @@
package tech.easyflow.manuagent.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.core.keygen.KeyGenerators;
import java.time.OffsetDateTime;
import java.util.UUID;
import tech.easyflow.manuagent.typehandler.UuidTypeHandler;
/**
* 映射 {@code app.app_user} 表的管理员用户实体。
*
* <p>该实体只服务于数据库持久化,不直接作为 HTTP 接口的输入或输出。UUID 主键继续由应用层生成,
* MyBatis-Flex 的 UUID 生成器只会在主键为空时补值,因此既能保留调用方已生成的 UUID也能避免
* 遗漏主键造成数据库约束错误。写入时使用 selective insert 保留已有 UUID
* 其余未赋值字段仍由数据库默认值负责填充。</p>
*/
@Table(value = "app_user", schema = "app")
public class AppUserEntity {
/** 用户主键。 */
@Id(keyType = KeyType.Generator, value = KeyGenerators.uuid)
@Column(typeHandler = UuidTypeHandler.class)
private UUID id;
/** 登录用户名。 */
private String username;
/** Spring Security 使用的密码摘要。 */
private String passwordHash;
/** 页面展示名称。 */
private String displayName;
/** 账户是否允许登录。 */
private Boolean enabled;
/** 最近一次登录时间。 */
private OffsetDateTime lastLoginAt;
/** 创建时间。 */
private OffsetDateTime createdAt;
/** 更新时间。 */
private OffsetDateTime updatedAt;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPasswordHash() {
return passwordHash;
}
public void setPasswordHash(String passwordHash) {
this.passwordHash = passwordHash;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public OffsetDateTime getLastLoginAt() {
return lastLoginAt;
}
public void setLastLoginAt(OffsetDateTime lastLoginAt) {
this.lastLoginAt = lastLoginAt;
}
public OffsetDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(OffsetDateTime createdAt) {
this.createdAt = createdAt;
}
public OffsetDateTime getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(OffsetDateTime updatedAt) {
this.updatedAt = updatedAt;
}
}

View File

@@ -0,0 +1,73 @@
package tech.easyflow.manuagent.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.keygen.KeyGenerators;
import java.time.OffsetDateTime;
import java.util.UUID;
import tech.easyflow.manuagent.typehandler.JsonbStringTypeHandler;
import tech.easyflow.manuagent.typehandler.UuidTypeHandler;
/**
* 映射 {@code app.artifact} 表的最终产物实体。
*/
@Table(value = "artifact", schema = "app")
public class ArtifactEntity {
/** 产物主键。 */
@Id(keyType = KeyType.Generator, value = KeyGenerators.uuid)
@Column(typeHandler = UuidTypeHandler.class)
private UUID id;
/** 所属项目。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID projectId;
/** 生成该产物的 Agent Run。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID runId;
/** 产物业务类型。 */
private String kind;
/** 下载文件名。 */
private String name;
/** 相对于项目根目录的受控路径。 */
private String relativePath;
/** 文件 MIME 类型。 */
private String mimeType;
/** 文件字节数。 */
private Long sizeBytes;
/** 文件内容 SHA-256。 */
private String sha256;
/** 业务元数据 JSON。 */
@Column(jdbcType = org.apache.ibatis.type.JdbcType.OTHER, typeHandler = JsonbStringTypeHandler.class)
private String metadataJson;
/** 最近发布时间。 */
private OffsetDateTime publishedAt;
/** 首次创建时间。 */
private OffsetDateTime createdAt;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public UUID getProjectId() { return projectId; }
public void setProjectId(UUID projectId) { this.projectId = projectId; }
public UUID getRunId() { return runId; }
public void setRunId(UUID runId) { this.runId = runId; }
public String getKind() { return kind; }
public void setKind(String kind) { this.kind = kind; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getRelativePath() { return relativePath; }
public void setRelativePath(String relativePath) { this.relativePath = relativePath; }
public String getMimeType() { return mimeType; }
public void setMimeType(String mimeType) { this.mimeType = mimeType; }
public Long getSizeBytes() { return sizeBytes; }
public void setSizeBytes(Long sizeBytes) { this.sizeBytes = sizeBytes; }
public String getSha256() { return sha256; }
public void setSha256(String sha256) { this.sha256 = sha256; }
public String getMetadataJson() { return metadataJson; }
public void setMetadataJson(String metadataJson) { this.metadataJson = metadataJson; }
public OffsetDateTime getPublishedAt() { return publishedAt; }
public void setPublishedAt(OffsetDateTime publishedAt) { this.publishedAt = publishedAt; }
public OffsetDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; }
}

View File

@@ -0,0 +1,37 @@
package tech.easyflow.manuagent.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.time.OffsetDateTime;
import java.util.UUID;
import tech.easyflow.manuagent.typehandler.UuidTypeHandler;
/**
* 映射 {@code app.model_assignment} 表的 Agent 角色模型分配实体。
*/
@Table(value = "model_assignment", schema = "app")
public class ModelAssignmentEntity {
/** Agent 角色,同时也是业务主键。 */
@Id(keyType = KeyType.None)
private String role;
/** 分配的模型配置。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID modelConfigId;
/** 执行分配的用户。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID assignedBy;
/** 最近更新时间。 */
private OffsetDateTime updatedAt;
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public UUID getModelConfigId() { return modelConfigId; }
public void setModelConfigId(UUID modelConfigId) { this.modelConfigId = modelConfigId; }
public UUID getAssignedBy() { return assignedBy; }
public void setAssignedBy(UUID assignedBy) { this.assignedBy = assignedBy; }
public OffsetDateTime getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; }
}

View File

@@ -0,0 +1,89 @@
package tech.easyflow.manuagent.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.keygen.KeyGenerators;
import java.time.OffsetDateTime;
import java.util.UUID;
import org.apache.ibatis.type.JdbcType;
import tech.easyflow.manuagent.typehandler.JsonbStringTypeHandler;
import tech.easyflow.manuagent.typehandler.UuidTypeHandler;
/**
* 映射 {@code app.model_config} 表的模型配置与加密密钥实体。
*
* <p>密钥字段始终保存 AES-GCM 密文;实体只在服务内部使用,严禁直接作为接口响应。</p>
*/
@Table(value = "model_config", schema = "app")
public class ModelConfigEntity {
/** 模型配置主键。 */
@Id(keyType = KeyType.Generator, value = KeyGenerators.uuid)
@Column(typeHandler = UuidTypeHandler.class)
private UUID id;
/** 配置名称。 */
private String name;
/** 模型服务商类型。 */
private String provider;
/** OpenAI 兼容 API 根地址。 */
private String baseUrl;
/** 上游模型标识。 */
private String modelId;
/** AES-GCM 加密后的 API Key。 */
private byte[] apiKeyCiphertext;
/** 仅用于界面展示的密钥尾号。 */
private String apiKeyHint;
/** 密钥加密格式版本。 */
private Short keyVersion;
/** 高级请求配置 JSON。 */
@Column(jdbcType = JdbcType.OTHER, typeHandler = JsonbStringTypeHandler.class)
private String configJson;
/** 模型能力 JSON。 */
@Column(jdbcType = JdbcType.OTHER, typeHandler = JsonbStringTypeHandler.class)
private String capabilitiesJson;
/** 是否启用。 */
private Boolean enabled;
/** 是否为全局默认模型。 */
@Column("is_default")
private Boolean defaultModel;
/** 创建用户。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID createdBy;
/** 创建时间。 */
private OffsetDateTime createdAt;
/** 更新时间。 */
private OffsetDateTime updatedAt;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getProvider() { return provider; }
public void setProvider(String provider) { this.provider = provider; }
public String getBaseUrl() { return baseUrl; }
public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; }
public String getModelId() { return modelId; }
public void setModelId(String modelId) { this.modelId = modelId; }
public byte[] getApiKeyCiphertext() { return apiKeyCiphertext; }
public void setApiKeyCiphertext(byte[] apiKeyCiphertext) { this.apiKeyCiphertext = apiKeyCiphertext; }
public String getApiKeyHint() { return apiKeyHint; }
public void setApiKeyHint(String apiKeyHint) { this.apiKeyHint = apiKeyHint; }
public Short getKeyVersion() { return keyVersion; }
public void setKeyVersion(Short keyVersion) { this.keyVersion = keyVersion; }
public String getConfigJson() { return configJson; }
public void setConfigJson(String configJson) { this.configJson = configJson; }
public String getCapabilitiesJson() { return capabilitiesJson; }
public void setCapabilitiesJson(String capabilitiesJson) { this.capabilitiesJson = capabilitiesJson; }
public Boolean getEnabled() { return enabled; }
public void setEnabled(Boolean enabled) { this.enabled = enabled; }
public Boolean getDefaultModel() { return defaultModel; }
public void setDefaultModel(Boolean defaultModel) { this.defaultModel = defaultModel; }
public UUID getCreatedBy() { return createdBy; }
public void setCreatedBy(UUID createdBy) { this.createdBy = createdBy; }
public OffsetDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; }
public OffsetDateTime getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; }
}

View File

@@ -0,0 +1,62 @@
package tech.easyflow.manuagent.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.keygen.KeyGenerators;
import java.time.OffsetDateTime;
import java.util.UUID;
import tech.easyflow.manuagent.typehandler.UuidTypeHandler;
/**
* 映射 {@code app.project} 表的企业申报项目实体。
*/
@Table(value = "project", schema = "app")
public class ProjectEntity {
/** 项目主键。 */
@Id(keyType = KeyType.Generator, value = KeyGenerators.uuid)
@Column(typeHandler = UuidTypeHandler.class)
private UUID id;
/** 企业名称。 */
private String companyName;
/** 项目显示名称。 */
private String projectName;
/** AgentScope/AG-UI 使用的线程标识。 */
private String aguiThreadId;
/** 申报等级。 */
private String applicationLevel;
/** 当前业务阶段。 */
private String status;
/** 创建用户。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID createdBy;
/** 业务版本号。 */
private Long version;
/** 创建时间。 */
private OffsetDateTime createdAt;
/** 更新时间。 */
private OffsetDateTime updatedAt;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getCompanyName() { return companyName; }
public void setCompanyName(String companyName) { this.companyName = companyName; }
public String getProjectName() { return projectName; }
public void setProjectName(String projectName) { this.projectName = projectName; }
public String getAguiThreadId() { return aguiThreadId; }
public void setAguiThreadId(String aguiThreadId) { this.aguiThreadId = aguiThreadId; }
public String getApplicationLevel() { return applicationLevel; }
public void setApplicationLevel(String applicationLevel) { this.applicationLevel = applicationLevel; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public UUID getCreatedBy() { return createdBy; }
public void setCreatedBy(UUID createdBy) { this.createdBy = createdBy; }
public Long getVersion() { return version; }
public void setVersion(Long version) { this.version = version; }
public OffsetDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; }
public OffsetDateTime getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; }
}

View File

@@ -0,0 +1,82 @@
package tech.easyflow.manuagent.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.keygen.KeyGenerators;
import java.time.OffsetDateTime;
import java.util.UUID;
import tech.easyflow.manuagent.typehandler.UuidTypeHandler;
/**
* 映射 {@code app.project_file} 表的项目材料实体。
*
* <p>实体保存文件的受控相对路径、完整性摘要及软删除状态;真实文件仍由
* {@code ProjectFileService} 在项目工作区内管理。</p>
*/
@Table(value = "project_file", schema = "app")
public class ProjectFileEntity {
/** 文件主键。 */
@Id(keyType = KeyType.Generator, value = KeyGenerators.uuid)
@Column(typeHandler = UuidTypeHandler.class)
private UUID id;
/** 所属项目主键。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID projectId;
/** 用户上传时的原始文件名。 */
private String originalName;
/** 工作区内实际保存的文件名。 */
private String storedName;
/** 相对于项目根目录的受控路径。 */
private String relativePath;
/** 内容检测得到的 MIME 类型。 */
private String mimeType;
/** 小写文件扩展名。 */
private String extension;
/** 文件字节数。 */
private Long sizeBytes;
/** 文件内容 SHA-256。 */
private String sha256;
/** 材料处理状态。 */
private String status;
/** 上传用户主键。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID uploadedBy;
/** 软删除时间,空值表示有效。 */
private OffsetDateTime deletedAt;
/** 创建时间。 */
private OffsetDateTime createdAt;
/** 更新时间。 */
private OffsetDateTime updatedAt;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public UUID getProjectId() { return projectId; }
public void setProjectId(UUID projectId) { this.projectId = projectId; }
public String getOriginalName() { return originalName; }
public void setOriginalName(String originalName) { this.originalName = originalName; }
public String getStoredName() { return storedName; }
public void setStoredName(String storedName) { this.storedName = storedName; }
public String getRelativePath() { return relativePath; }
public void setRelativePath(String relativePath) { this.relativePath = relativePath; }
public String getMimeType() { return mimeType; }
public void setMimeType(String mimeType) { this.mimeType = mimeType; }
public String getExtension() { return extension; }
public void setExtension(String extension) { this.extension = extension; }
public Long getSizeBytes() { return sizeBytes; }
public void setSizeBytes(Long sizeBytes) { this.sizeBytes = sizeBytes; }
public String getSha256() { return sha256; }
public void setSha256(String sha256) { this.sha256 = sha256; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public UUID getUploadedBy() { return uploadedBy; }
public void setUploadedBy(UUID uploadedBy) { this.uploadedBy = uploadedBy; }
public OffsetDateTime getDeletedAt() { return deletedAt; }
public void setDeletedAt(OffsetDateTime deletedAt) { this.deletedAt = deletedAt; }
public OffsetDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; }
public OffsetDateTime getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; }
}

View File

@@ -0,0 +1,67 @@
package tech.easyflow.manuagent.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.keygen.KeyGenerators;
import java.time.OffsetDateTime;
import java.util.UUID;
import org.apache.ibatis.type.JdbcType;
import tech.easyflow.manuagent.typehandler.JsonbStringTypeHandler;
import tech.easyflow.manuagent.typehandler.UuidTypeHandler;
/**
* 映射 {@code app.project_plan} 表的不可变规划版本实体。
*/
@Table(value = "project_plan", schema = "app")
public class ProjectPlanEntity {
/** 规划主键。 */
@Id(keyType = KeyType.Generator, value = KeyGenerators.uuid)
@Column(typeHandler = UuidTypeHandler.class)
private UUID id;
/** 所属项目。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID projectId;
/** 项目内递增版本号。 */
private Integer planVersion;
/** 草稿、已确认或已取代状态。 */
private String status;
/** 完整规划 JSON。 */
@Column(jdbcType = JdbcType.OTHER, typeHandler = JsonbStringTypeHandler.class)
private String planJson;
/** 创建用户。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID createdBy;
/** 确认用户。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID confirmedBy;
/** 确认时间。 */
private OffsetDateTime confirmedAt;
/** 创建时间。 */
private OffsetDateTime createdAt;
/** 更新时间。 */
private OffsetDateTime updatedAt;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public UUID getProjectId() { return projectId; }
public void setProjectId(UUID projectId) { this.projectId = projectId; }
public Integer getPlanVersion() { return planVersion; }
public void setPlanVersion(Integer planVersion) { this.planVersion = planVersion; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getPlanJson() { return planJson; }
public void setPlanJson(String planJson) { this.planJson = planJson; }
public UUID getCreatedBy() { return createdBy; }
public void setCreatedBy(UUID createdBy) { this.createdBy = createdBy; }
public UUID getConfirmedBy() { return confirmedBy; }
public void setConfirmedBy(UUID confirmedBy) { this.confirmedBy = confirmedBy; }
public OffsetDateTime getConfirmedAt() { return confirmedAt; }
public void setConfirmedAt(OffsetDateTime confirmedAt) { this.confirmedAt = confirmedAt; }
public OffsetDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; }
public OffsetDateTime getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; }
}

View File

@@ -0,0 +1,66 @@
package tech.easyflow.manuagent.entity;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import java.time.OffsetDateTime;
import java.util.UUID;
import tech.easyflow.manuagent.typehandler.UuidTypeHandler;
/**
* 映射应用自管的 {@code app.skill_config} 表。
*
* <p>Skill 正文和资源不属于该实体,它们继续由 AgentScope 的 PostgreSQL repository 管理。</p>
*/
@Table(value = "skill_config", schema = "app")
public class SkillConfigEntity {
/** Skill 标准名称,同时引用 AgentScope Skill 主表。 */
@Id(keyType = KeyType.None)
private String skillName;
/** Skill 包版本。 */
private String version;
/** BUILTIN 或 IMPORTED。 */
private String sourceType;
/** 是否允许 Agent 使用。 */
private Boolean enabled;
/** 是否禁止从界面编辑内容。 */
private Boolean readOnly;
/** Skill 包内容摘要。 */
private String checksum;
/** VALID 或 INVALID。 */
private String validationStatus;
/** 校验失败说明。 */
private String validationMessage;
/** 导入用户。 */
@Column(typeHandler = UuidTypeHandler.class)
private UUID importedBy;
/** 创建时间。 */
private OffsetDateTime createdAt;
/** 更新时间。 */
private OffsetDateTime updatedAt;
public String getSkillName() { return skillName; }
public void setSkillName(String skillName) { this.skillName = skillName; }
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
public String getSourceType() { return sourceType; }
public void setSourceType(String sourceType) { this.sourceType = sourceType; }
public Boolean getEnabled() { return enabled; }
public void setEnabled(Boolean enabled) { this.enabled = enabled; }
public Boolean getReadOnly() { return readOnly; }
public void setReadOnly(Boolean readOnly) { this.readOnly = readOnly; }
public String getChecksum() { return checksum; }
public void setChecksum(String checksum) { this.checksum = checksum; }
public String getValidationStatus() { return validationStatus; }
public void setValidationStatus(String validationStatus) { this.validationStatus = validationStatus; }
public String getValidationMessage() { return validationMessage; }
public void setValidationMessage(String validationMessage) { this.validationMessage = validationMessage; }
public UUID getImportedBy() { return importedBy; }
public void setImportedBy(UUID importedBy) { this.importedBy = importedBy; }
public OffsetDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; }
public OffsetDateTime getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(OffsetDateTime updatedAt) { this.updatedAt = updatedAt; }
}