# 实体类与数据库脚本同步示例 ## 基础同步示例 ### 示例1: 简单用户实体 **Java实体类 (User.java):** ```java package com.fundplatform.user.entity; import javax.persistence.*; import java.time.LocalDateTime; @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "username", length = 50, nullable = false, unique = true) private String username; @Column(name = "email", length = 100) private String email; @Column(name = "phone", length = 20) private String phone; @Column(name = "is_active", columnDefinition = "TINYINT(1) DEFAULT 1") private Boolean active; @Column(name = "created_time", updatable = false) private LocalDateTime createdTime; @Column(name = "updated_time") private LocalDateTime updatedTime; // getters and setters... } ``` **对应SQL脚本 (user.sql):** ```sql CREATE TABLE `user` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '用户ID', `username` VARCHAR(50) NOT NULL COMMENT '用户名', `email` VARCHAR(100) COMMENT '邮箱地址', `phone` VARCHAR(20) COMMENT '手机号码', `is_active` TINYINT(1) DEFAULT 1 COMMENT '是否激活', `created_time` DATETIME COMMENT '创建时间', `updated_time` DATETIME COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`), KEY `idx_email` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户基本信息表'; ``` ### 示例2: 订单实体(复杂类型) **Java实体类 (Order.java):** ```java package com.fundplatform.order.entity; import javax.persistence.*; import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; @Entity @Table(name = "fund_order") public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long orderId; @Column(name = "order_no", length = 32, nullable = false, unique = true) private String orderNo; @Column(name = "customer_id", nullable = false) private Long customerId; @Column(name = "project_id") private Long projectId; @Column(name = "amount", precision = 15, scale = 2, nullable = false) private BigDecimal amount; @Column(name = "order_date", nullable = false) private LocalDate orderDate; @Enumerated(EnumType.STRING) @Column(name = "order_status", length = 20, nullable = false) private OrderStatus status; @Column(name = "payment_method", length = 20) private String paymentMethod; @Column(name = "remark", length = 500) private String remark; // 枚举定义 public enum OrderStatus { PENDING, CONFIRMED, PROCESSING, COMPLETED, CANCELLED } } ``` **对应SQL脚本 (fund_order.sql):** ```sql CREATE TABLE `fund_order` ( `order_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '订单ID', `order_no` VARCHAR(32) NOT NULL COMMENT '订单编号', `customer_id` BIGINT NOT NULL COMMENT '客户ID', `project_id` BIGINT COMMENT '项目ID', `amount` DECIMAL(15,2) NOT NULL COMMENT '订单金额', `order_date` DATE NOT NULL COMMENT '下单日期', `order_status` VARCHAR(20) NOT NULL COMMENT '订单状态', `payment_method` VARCHAR(20) COMMENT '支付方式', `remark` VARCHAR(500) COMMENT '备注', `created_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updated_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`order_id`), UNIQUE KEY `uk_order_no` (`order_no`), KEY `idx_customer_id` (`customer_id`), KEY `idx_order_date` (`order_date`), KEY `idx_order_status` (`order_status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='基金订单表'; ``` ## 字段变更同步示例 ### 场景1: 添加新字段 **原始实体类:** ```java @Entity @Table(name = "product") public class Product { @Id private Long id; @Column(length = 100) private String name; @Column(precision = 10, scale = 2) private BigDecimal price; } ``` **修改后的实体类:** ```java @Entity @Table(name = "product") public class Product { @Id private Long id; @Column(length = 100, nullable = false) // 添加非空约束 private String name; @Column(precision = 10, scale = 2, nullable = false) // 添加非空约束 private BigDecimal price; // 新增字段 @Column(name = "category_id") private Long categoryId; @Column(length = 500) private String description; @Column(name = "is_available", columnDefinition = "TINYINT(1) DEFAULT 1") private Boolean available; } ``` **变更脚本生成:** ```bash # 使用变更脚本生成器 python3 scripts/generate-change-scripts.py \ --entity fund-product/src/main/java/com/fundplatform/product/entity/Product.java \ --version v1.1.0 \ --description "为产品表添加分类和描述字段" # 生成的脚本文件位置(部署目录) deploy/sql/upgrade/v1.1.0/20240115_add_product_fields.sql deploy/sql/upgrade/v1.1.0/rollback/20240115_add_product_fields_rollback.sql ``` **生成的正向变更脚本 (20240115_add_product_fields.sql):** ```sql -- ============================================ -- 变更描述: 为产品表添加分类和描述字段 -- 变更时间: 2024-01-15 14:30:00 -- 影响版本: v1.1.0 -- 影响表: product -- ============================================ -- 1. 添加字段 ALTER TABLE `product` ADD COLUMN `category_id` BIGINT COMMENT '分类ID', ADD COLUMN `description` VARCHAR(500) COMMENT '产品描述', ADD COLUMN `is_available` TINYINT(1) DEFAULT 1 COMMENT '是否可用'; -- 2. 添加索引 ALTER TABLE `product` ADD INDEX `idx_category_id` (`category_id`); -- 3. 验证变更 SELECT COUNT(*) as new_columns FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'product' AND COLUMN_NAME IN ('category_id', 'description', 'is_available'); ``` **生成的回滚脚本 (20240115_add_product_fields_rollback.sql):** ```sql -- ============================================ -- 回滚描述: 撤销产品表字段添加变更 -- 回滚时间: 2024-01-15 14:30:00 -- 原版本: v1.1.0 -- 影响表: product -- ============================================ -- 1. 删除索引 ALTER TABLE `product` DROP INDEX `idx_category_id`; -- 2. 删除字段 ALTER TABLE `product` DROP COLUMN `category_id`, DROP COLUMN `description`, DROP COLUMN `is_available`; -- 3. 验证回滚 SELECT COUNT(*) as remaining_new_columns FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'product' AND COLUMN_NAME IN ('category_id', 'description', 'is_available'); ``` ### 场景2: 字段类型变更 **实体类变更:** ```java // 原始:String类型存储状态 @Column(length = 20) private String status; // 修改为:枚举类型 @Enumerated(EnumType.STRING) @Column(length = 20) private OrderStatus status; public enum OrderStatus { DRAFT, SUBMITTED, APPROVED, REJECTED } ``` **变更脚本:** ```sql -- 20240120_modify_order_status_type.sql -- ============================================ -- 变更描述: 修改订单状态字段类型为枚举 -- 变更时间: 2024-01-20 -- ============================================ -- 1. 添加新字段 ALTER TABLE `order` ADD COLUMN `status_enum` VARCHAR(20) COMMENT '订单状态(枚举)'; -- 2. 数据迁移 UPDATE `order` SET `status_enum` = `status` WHERE `status` IN ('DRAFT', 'SUBMITTED', 'APPROVED', 'REJECTED'); -- 3. 删除旧字段 ALTER TABLE `order` DROP COLUMN `status`; -- 4. 重命名新字段 ALTER TABLE `order` CHANGE `status_enum` `status` VARCHAR(20) COMMENT '订单状态'; -- 5. 添加约束 ALTER TABLE `order` ADD CONSTRAINT `chk_status_values` CHECK (`status` IN ('DRAFT', 'SUBMITTED', 'APPROVED', 'REJECTED')); ``` ## 文档同步示例 ### 场景3: 设计文档更新 **更新数据库设计文档:** ```markdown # product 表结构文档 ## 表基本信息 - **表名**: `product` - **描述**: 产品信息表 - **引擎**: InnoDB - **字符集**: utf8mb4 ## 字段定义 | 字段名 | 类型 | 允许NULL | 默认值 | 描述 | |--------|------|----------|--------|------| | id | BIGINT | NO | AUTO_INCREMENT | 产品ID | | name | VARCHAR(100) | NO | | 产品名称 | | price | DECIMAL(10,2) | NO | | 产品价格 | | category_id | BIGINT | YES | NULL | 分类ID | | description | VARCHAR(500) | YES | NULL | 产品描述 | | is_available | TINYINT(1) | YES | 1 | 是否可用 | | created_time | DATETIME | YES | CURRENT_TIMESTAMP | 创建时间 | | updated_time | DATETIME | YES | CURRENT_TIMESTAMP | 更新时间 | ## 索引信息 | 索引名 | 类型 | 字段 | 描述 | |--------|------|------|------| | PRIMARY | PRIMARY | id | 主键索引 | | idx_category_id | NORMAL | category_id | 分类索引 | ## 变更历史 | 日期 | 版本 | 变更描述 | 变更人 | |------|------|----------|--------| | 2024-01-15 | v1.1.0 | 添加分类ID、产品描述和可用状态字段 | Zhang San | | 2024-01-10 | v1.0.0 | 初始版本 | Li Si | ``` **API文档更新:** ```markdown # 产品管理API接口 ## GET /api/products 获取产品列表 ### 请求参数 | 参数名 | 类型 | 必填 | 描述 | |--------|------|------|------| | categoryId | Long | 否 | 分类产品筛选 | | available | Boolean | 否 | 可用性筛选 | ### 响应示例 ```json { "code": 200, "data": { "records": [ { "id": 1, "name": "基金产品A", "price": 100.50, "categoryId": 1, "description": "这是一款优质基金产品", "available": true, "createdTime": "2024-01-15T10:30:00" } ] } } ``` ``` ## 生产环境部署示例 ### 场景4: 生产环境变更流程 **变更申请表:** ```markdown # 数据库变更申请 ## 基本信息 - **申请人**: 张三 - **申请时间**: 2024-01-15 15:00 - **变更类型**: 字段添加 - **影响系统**: 产品管理系统 - **预计 downtime**: 5分钟 ## 变更详情 - **变更SQL**: src/main/resources/sql/upgrade/v1.1.0/20240115_add_product_fields.sql - **回滚SQL**: src/main/resources/sql/upgrade/v1.1.0/rollback/20240115_add_product_fields_rollback.sql - **验证SQL**: src/main/resources/sql/upgrade/v1.1.0/verify/20240115_add_product_fields_verify.sql ## 风险评估 - [x] 数据备份已完成 - [x] 回滚方案已准备 - [x] 测试环境验证通过 - [x] 监控告警已设置 ## 执行计划 1. 20:00 - 开始变更 2. 20:01 - 执行备份 3. 20:02 - 执行变更脚本 4. 20:03 - 执行验证脚本 5. 20:04 - 功能测试 6. 20:05 - 变更完成 ``` **生产环境执行脚本:** ```bash #!/bin/bash # production-deploy.sh set -e echo "=== 生产环境数据库变更部署 ===" echo "变更版本: v1.1.0" echo "执行时间: $(date)" echo "" # 1. 环境检查 echo "1. 环境检查..." if [ -z "$DB_HOST" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ]; then echo "❌ 数据库连接信息不完整" exit 1 fi # 2. 数据库备份 echo "2. 执行数据库备份..." BACKUP_FILE="/backup/proddb_$(date +%Y%m%d_%H%M%S).sql" mysqldump -h$DB_HOST -u$DB_USER -p$DB_PASSWORD fund_platform > $BACKUP_FILE echo "✓ 备份完成: $BACKUP_FILE" # 3. 执行变更(使用部署目录) echo "3. 执行变更脚本..." mysql -h$DB_HOST -u$DB_USER -p$DB_PASSWORD fund_platform < \ deploy/sql/upgrade/v1.1.0/20240115_add_product_fields.sql # 4. 验证变更 echo "4. 验证变更结果..." mysql -h$DB_HOST -u$DB_USER -p$DB_PASSWORD fund_platform < \ deploy/sql/upgrade/v1.1.0/verify/20240115_add_product_fields_verify.sql # 5. 记录变更日志 echo "5. 记录变更日志..." mysql -h$DB_HOST -u$DB_USER -p$DB_PASSWORD fund_platform << EOF INSERT INTO db_changelog (version, script_name, execute_time, operator, environment) VALUES ('v1.1.0', '20240115_add_product_fields.sql', NOW(), '$USER', 'production'); EOF echo "✓ 变更部署完成" echo "请进行业务功能验证" ``` ## 自动化验证示例 ### 验证脚本使用 **单个实体验证:** ```bash # 验证用户实体与数据库脚本同步性 python3 scripts/validate-entity-db-sync.py \ fund-user/src/main/java/com/fundplatform/user/entity/User.java \ fund-user/src/main/resources/sql/init/user.sql # 输出示例: # ✅ 字段一致: id -> id (BIGINT) # ✅ 字段一致: username -> username (VARCHAR(50)) # ⚠️ 新增字段: phone (数据库中缺失) # ❌ 类型不匹配: email长度应为100,当前为50 ``` **批量验证:** ```bash # 验证所有模块的实体同步性 ./scripts/batch-validate-sync.sh # 输出示例: # === 批量验证实体类与数据库脚本同步 === # 检查: User -> user # ✅ 实体类与数据库脚本同步一致 # # 检查: Order -> fund_order # ⚠️ 发现3个不一致项 # ❌ 字段email长度不匹配 # ⚠️ 缺少字段phone # ⚠️ 缺少字段description # # === 检查完成 === # 错误: 1 # 警告: 2 ``` ### CI集成配置 **GitHub Actions配置:** ```yaml name: Entity-DB Sync Check on: [push, pull_request] jobs: sync-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Python uses: actions/setup-python@v4 with: python-version: '3.9' - name: Install dependencies run: pip install mysql-connector-python - name: Run sync validation run: | chmod +x scripts/batch-validate-sync.sh ./scripts/batch-validate-sync.sh - name: Generate change scripts if: github.event_name == 'pull_request' run: | python3 scripts/generate-change-scripts.py --auto-generate - name: Upload artifacts if: failure() uses: actions/upload-artifact@v3 with: name: sync-report path: sync-report.txt ``` **Git Pre-commit Hook:** ```bash #!/bin/bash # .git/hooks/pre-commit # 检查是否有实体类修改 if git diff --cached --name-only | grep -q "entity/.*\.java"; then echo "检测到实体类修改,运行同步检查..." # 执行验证 if ! ./scripts/batch-validate-sync.sh; then echo "❌ 实体类与数据库脚本不同步,请修复后再提交" echo "提示:运行 'python3 scripts/generate-sql-from-entity.py ' 生成SQL" exit 1 fi # 自动生成变更脚本 echo "生成变更脚本..." python3 scripts/generate-change-scripts.py --auto-generate echo "✅ 同步检查通过" fi ``` 这些示例展示了从简单到复杂的各种同步场景,包括变更脚本生成、文档同步和生产环境部署的完整流程。