# UUID 生成重构:统一使用 Python 层生成 **日期**: 2026-01-27 **类型**: 重构 **影响范围**: 所有表主键生成逻辑 ## 变更概述 将所有表的 UUID 主键生成从数据库层(`gen_uuid_v7()` 函数)迁移到 Python 应用层(`generate_uuid` 函数),统一 UUID 生成逻辑。 ## 变更详情 ### 1. Model 层修改 #### AI 服务 Models(4 个文件) **修复主键类型和默认值**: - `server/app/models/ai_model.py` - `model_id`: `sa.Text()` + `server_default="gen_uuid_v7()"` → `sa.UUID()` + `default=generate_uuid` - `server/app/models/ai_quota.py` - `quota_id`: `sa.Text()` + `server_default="gen_uuid_v7()"` → `sa.UUID()` + `default=generate_uuid` - `server/app/models/ai_job.py` - `ai_job_id`: `sa.Text()` + `server_default="gen_uuid_v7()"` → `sa.UUID()` + `default=generate_uuid` - `storyboard_id`: `sa.Text()` → `sa.UUID()` - `consumption_log_id`: `sa.Text()` → `sa.UUID()` - `model_id`: `sa.Text()` → `sa.UUID()` - `server/app/models/ai_usage_log.py` - `usage_log_id`: `sa.Text()` + `server_default="gen_uuid_v7()"` → `sa.UUID()` + `default=generate_uuid` - `ai_job_id`: `sa.Text()` → `sa.UUID()` - `model_id`: `sa.Text()` → `sa.UUID()` #### Credit Models(1 个文件) **移除数据库默认值**: - `server/app/models/credit.py` - `transaction_id`: 移除 `server_default=text("gen_uuid_v7()")`,改用 `default=generate_uuid` - `consumption_id`: 移除 `server_default=text("gen_uuid_v7()")`,改用 `default=generate_uuid` - `package_id`: 移除 `server_default=text("gen_uuid_v7()")`,改用 `default=generate_uuid` - `pricing_id`: 移除 `server_default=text("gen_uuid_v7()")`,改用 `default=generate_uuid` - `gift_id`: 移除 `server_default=text("gen_uuid_v7()")`,改用 `default=generate_uuid` ### 2. 数据库迁移 **Alembic 迁移**: `20260127_2006_300b80f7e512_remove_gen_uuid_v7_function_.py` **变更内容**: - 移除所有表主键的 `server_default` - 修改 AI 服务表主键类型从 `TEXT` 改为 `UUID` - 修改 AI 服务表关联字段类型从 `TEXT` 改为 `UUID` **影响的表**: - `ai_models` - 主键类型修正 - `ai_quotas` - 主键类型修正 - `ai_jobs` - 主键和关联字段类型修正 - `ai_usage_logs` - 主键和关联字段类型修正 - `credit_transactions` - 移除 server_default - `credit_consumption_logs` - 移除 server_default - `credit_packages` - 移除 server_default - `credit_pricing` - 移除 server_default - `credit_gifts` - 移除 server_default ## 技术细节 ### UUID 生成方式 **之前**: ```python # Model 定义 model_id: Optional[str] = Field( default=None, sa_column=Column(Text, primary_key=True, server_default="gen_uuid_v7()") ) # 数据库函数 CREATE OR REPLACE FUNCTION gen_uuid_v7() RETURNS uuid AS $$ -- PostgreSQL 函数实现 $$ LANGUAGE plpgsql VOLATILE; ``` **现在**: ```python # Model 定义 model_id: UUID = Field( sa_column=Column(PG_UUID(as_uuid=True), primary_key=True, default=generate_uuid) ) # Python 函数 from uuid_utils import uuid7 def generate_uuid() -> UUID: return uuid7() ``` ### 优势 1. **逻辑统一**:所有 UUID 生成逻辑集中在 Python 层 2. **易于测试**:可以在测试中 Mock `generate_uuid` 函数 3. **类型安全**:使用 `UUID` 类型而非 `TEXT`,避免类型不一致 4. **简化部署**:无需维护数据库函数 5. **符合架构原则**:应用层控制业务逻辑 ## 兼容性 - ✅ **向后兼容**:现有数据不受影响 - ✅ **迁移安全**:Alembic 自动生成迁移脚本 - ✅ **回滚支持**:提供完整的 downgrade 逻辑 ## 部署步骤 1. 更新代码到最新版本 2. 执行数据库迁移: ```bash docker exec jointo-server-app alembic upgrade head ``` 3. 重启应用服务 ## 注意事项 - 迁移过程中会修改表结构,建议在低峰期执行 - 迁移完成后,数据库中的 `gen_uuid_v7()` 函数仍然存在但不再使用 - 新创建的记录将由 Python 层生成 UUID ## 相关文件 - Models: `server/app/models/ai_*.py`, `server/app/models/credit.py` - 迁移: `server/alembic/versions/20260127_2006_300b80f7e512_*.py` - UUID 生成器: `server/app/utils/id_generator.py`