FastbuildAI后端数据库模块注册分析
1. 概述
DatabaseModule
是 FastbuildAI 后端应用的核心数据库模块,负责配置和管理与 PostgreSQL 数据库的连接。该模块使用 TypeORM 作为 ORM 框架,提供了完整的数据库初始化、实体管理、连接配置和日志记录功能。
主要职责
- 配置 PostgreSQL 数据库连接
- 管理实体注册和同步
- 提供数据库初始化服务
- 集成业务模块的数据访问层
- 实现自定义日志记录和监控
2. 模块装饰器分析
// 源码位置:apps/server/src/core/database/database.module.ts
@Module({imports: [// DatabaseSyncModule,TypeOrmModule.forRootAsync({imports: [],inject: [],useFactory: () => {return {...appConfig.database,logger: new CustomLogger(),entities: ["dist/common/**/*.entity.js","dist/modules/**/*.entity.js","dist/core/**/*.entity.js",// "dist/plugins/**/*.entity.js",],synchronize: appConfig.database.synchronize,};},dataSourceFactory: async (options: PostgresConnectionOptions) => {const dataSource = await new DataSource({...options,logging: false,}).initialize();// 查询并打印数据库类型和版本信息try {const dbInfoResult = await dataSource.query("SELECT VERSION() as version");const dbVersion = dbInfoResult[0]?.version;TerminalLogger.info("PgSQL Version",dbVersion? dbVersion.match(/PostgreSQL\s+(\d+(?:\.\d+)?)/)[1]: "Unknown version",);} catch (error) {TerminalLogger.error("Database Error", `Get version failed: ${error.message}`);}TerminalLogger.success("PgSQL Status", "Connected");TerminalLogger.log("Db Sync", options.synchronize ? "ON" : "OFF", {color: "magenta",});if (process.env.LOG_DATABASE_SCHEMA === "true") {printEntityTable(dataSource);}return dataSource;},}),MenuModule,PermissionModule,DictModule,DecorateModule,TypeOrmModule.forFeature([User, Menu, Payconfig, Dict, AiProvider, AiModel, KeyTemplate]),],controllers: [],providers: [DatabaseInitService],exports: [DatabaseInitService],
})
export class DatabaseModule {}
配置说明
- imports: 导入 TypeORM 根模块和相关业务模块
- providers: 提供数据库初始化服务
- exports: 导出初始化服务供其他模块使用
3. TypeORM异步配置分析
3.1 配置工厂函数
// 源码位置:apps/server/src/core/database/database.module.ts
useFactory: () => {return {...appConfig.database,logger: new CustomLogger(),entities: ["dist/common/**/*.entity.js","dist/modules/**/*.entity.js","dist/core/**/*.entity.js",],synchronize: appConfig.database.synchronize,};
}
关键配置项:
- …appConfig.database - 从应用配置中获取数据库连接信息(主机、端口、用户名、密码等)
- logger: new CustomLogger() - 使用自定义日志记录器来记录 SQL 操作
- entities - 指定实体文件的路径模式,TypeORM 会自动扫描这些路径下的实体类
- synchronize - 控制是否自动同步数据库结构(开发环境通常为 true,生产环境为 false)
3.2 数据库配置接口
// 源码位置:apps/server/src/common/config/app.config.ts
export interface AppConfig {database: {type: "postgres";host: string;port: number;username: string;password: string;database: string;synchronize: boolean;logging: boolean;namingStrategy: NamingStrategyInterface;};
}export const appConfig: AppConfig = {database: {type: process.env.DB_TYPE as "postgres",host: process.env.DB_HOST,port: Number(process.env.DB_PORT),username: process.env.DB_USERNAME,password: process.env.DB_PASSWORD,database: process.env.DB_DATABASE,synchronize: process.env.DB_SYNCHRONIZE === "true",logging: process.env.DB_LOGGING === "true",namingStrategy: new SnakeNamingStrategy(),},
};
4. 数据源工厂分析
4.1 数据源初始化
// 源码位置:apps/server/src/core/database/database.module.ts
dataSourceFactory: async (options: PostgresConnectionOptions) => {const dataSource = await new DataSource({...options,logging: false,}).initialize();// 查询并打印数据库版本信息try {const dbInfoResult = await dataSource.query("SELECT VERSION() as version");const dbVersion = dbInfoResult[0]?.version;TerminalLogger.info("PgSQL Version",dbVersion? dbVersion.match(/PostgreSQL\s+(\d+(?:\.\d+)?)/)[1]: "Unknown version",);} catch (error) {TerminalLogger.error("Database Error", `Get version failed: ${error.message}`);}TerminalLogger.success("PgSQL Status", "Connected");TerminalLogger.log("Db Sync", options.synchronize ? "ON" : "OFF", {color: "magenta",});if (process.env.LOG_DATABASE_SCHEMA === "true") {printEntityTable(dataSource);}return dataSource;
}
功能说明:
- 创建 PostgreSQL 数据库连接
- 查询并显示数据库版本信息
- 输出连接状态和同步设置
- 根据环境变量决定是否打印数据库结构信息
4.2 功能特性
- 版本检测: 自动检测 PostgreSQL 版本
- 连接状态监控: 实时显示连接状态
- 同步状态显示: 显示数据库同步开关状态
- 实体表格打印: 可选的实体信息展示
5. 实体管理
5.1 实体扫描配置
// 源码位置:apps/server/src/core/database/database.module.ts
entities: ["dist/common/**/*.entity.js","dist/modules/**/*.entity.js","dist/core/**/*.entity.js",
]
5.2 特定实体注册
// 源码位置:apps/server/src/core/database/database.module.ts
TypeOrmModule.forFeature([User, // 用户实体Menu, // 菜单实体Payconfig, // 支付配置实体Dict, // 字典配置实体AiProvider, // AI提供商实体AiModel, // AI模型实体KeyTemplate // 密钥模板实体
])
TypeOrmModule.forFeature() 注册了具体的实体类,使这些实体可以在当前模块中使用。
5.3 实体示例
// 源码位置:apps/server/src/common/modules/dict/entities/dict.entity.ts
@AppEntity({ name: "config", comment: "系统配置字典" })
@Index("UQ_dict_key_group", ["key", "group"], { unique: true })
export class Dict {@PrimaryGeneratedColumn("uuid")id: string;@Column({ length: 100, comment: "配置键" })key: string;@Column({ type: "text", comment: "配置值(JSON格式)" })value: string;@Column({ length: 50, default: "default", comment: "配置分组" })group: string;@Column({ length: 255, nullable: true, comment: "配置描述" })description: string;@Column({ type: "int", default: 0, comment: "排序" })sort: number;@Column({ type: "boolean", default: true, comment: "是否启用" })isEnabled: boolean;@CreateDateColumn({ comment: "创建时间" })createdAt: Date;@UpdateDateColumn({ comment: "更新时间" })updatedAt: Date;
}
6. 业务模块集成
6.1 导入的功能模块
// 源码位置:apps/server/src/core/database/database.module.ts
imports: [MenuModule, // 菜单管理模块PermissionModule, // 权限管理模块DictModule, // 字典配置模块DecorateModule, // 装饰器模块
]
6.2 模块依赖关系
- MenuModule: 提供系统菜单管理功能
- PermissionModule: 提供权限控制和验证
- DictModule: 提供系统配置字典服务
- DecorateModule: 提供装饰器增强功能
7. 数据库初始化服务
7.1 服务概述
// 源码位置:apps/server/src/core/database/database-init.service.ts
@Injectable()
export class DatabaseInitService implements OnModuleInit {private readonly logger = new Logger(DatabaseInitService.name);constructor(private readonly dataSource: DataSource,private readonly permissionService: PermissionService,private readonly dictService: DictService,private readonly pageService: PageService,@InjectRepository(User) private readonly userRepository: Repository<User>,@InjectRepository(Menu) private readonly menuRepository: Repository<Menu>,@InjectRepository(Payconfig) private readonly payConfigRepository: Repository<Payconfig>,@InjectRepository(AiProvider) private readonly aiProviderRepository: Repository<AiProvider>,@InjectRepository(AiModel) private readonly aiModelRepository: Repository<AiModel>,@InjectRepository(KeyTemplate) private readonly keyTemplateRepository: Repository<KeyTemplate>,) {}
}
7.2 初始化流程
// 源码位置:apps/server/src/core/database/database-init.service.ts
async onModuleInit() {try {// 检查是否已安装const isInstalled = await this.checkInstallation();if (!isInstalled) {await this.initializeDatabase();} else {await this.checkAndUpgrade();}} catch (error) {this.logger.error('数据库初始化失败', error);}
}private async initializeDatabase() {await this.initializeUsers(); // 初始化用户await this.syncPermissions(); // 同步权限await this.initializeMenus(); // 初始化菜单await this.initializePayConfigs(); // 初始化支付配置await this.initializeAiProviders(); // 初始化AI提供商await this.initializeKeyTemplates(); // 初始化密钥模板
}
8. 自定义日志记录器
8.1 CustomLogger 实现
// 源码位置:apps/server/src/core/database/database.module.ts
class CustomLogger implements TypeOrmLogger {log(level: "log" | "info" | "warn", message: any): void {if (message && typeof message === "string" && message.includes("synchronize schema")) {TerminalLogger.info("Database", "Starting database schema synchronization...");}}logQuery(query: string): void {// 检测创建表的查询if (query.includes("CREATE TABLE")) {const tableName = query.match(/CREATE TABLE "?([^\s"]+)"?/)?.[1];if (tableName) {TerminalLogger.log("Table", `${tableName} created or updated`);}}// 检测添加外键的查询else if (query.includes("ADD CONSTRAINT") && query.includes("FOREIGN KEY")) {const match = query.match(/ADD CONSTRAINT "?([^\s"]+)"? FOREIGN KEY.*REFERENCES "?([^\s"(]+)"?/s,);if (match && match.length >= 3) {const constraintName = match[1];const referencedTable = match[2];TerminalLogger.log("Foreign Key",`${constraintName} added, references table ${referencedTable}`,);}}// 检测添加索引的查询else if (query.includes("CREATE INDEX")) {const indexMatch = query.match(/CREATE INDEX "?([^\s"]+)"? ON "?([^\s"]+)"?/i);if (indexMatch && indexMatch.length >= 3) {const indexName = indexMatch[1];const tableName = indexMatch[2];TerminalLogger.log("Index", `${indexName} added to table ${tableName}`);}}}logQueryError(error: string | Error, query: string): void {TerminalLogger.error("Query Error", error.toString());TerminalLogger.error("Failed Query", query);}logQuerySlow(time: number, query: string): void {TerminalLogger.warn("Slow Query", `(${time}ms): ${query}`);}logMigration(message: string): void {TerminalLogger.info("Migration", message);}logSchemaBuild(message: string): void {TerminalLogger.info("Schema Build", message);}
}
8.2 日志功能特性
- 表创建监控: 实时显示表的创建和更新
- 外键约束跟踪: 监控外键约束的添加
- 索引创建记录: 记录索引的创建过程
- 慢查询警告: 标记执行时间过长的查询
- 错误详细记录: 详细记录查询错误信息
9. 实体信息展示功能
9.1 printEntityTable 函数
// 源码位置:apps/server/src/core/database/database.module.ts
async function printEntityTable(dataSource: DataSource): Promise<void> {const entities = dataSource.entityMetadatas;if (entities.length === 0) {TerminalLogger.warn(`Entities`, "No entities registered");return;}// 创建表格const table = new Table({chars: table3BorderStyle,head: ["表名", "实体名", "注释", "模块", "列数", "关系数", "索引数"],style: {head: ["cyan"],border: ["gray"],},});// 对实体按模块分组排序const sortedEntities = [...entities].sort((a, b) => {const moduleA = getEntityModule(a);const moduleB = getEntityModule(b);return moduleA.localeCompare(moduleB);});// 添加实体信息到表格for (let i = 0; i < sortedEntities.length; i++) {const entity = sortedEntities[i];table.push([chalk.magenta(entity.tableName),entity.name,entity.comment || "-",getEntityModule(entity),entity.columns.length.toString(),entity.relations.length.toString(),entity.indices.length.toString(),]);}// 打印表格TerminalLogger.log("", `DataSource(${entities.length}):`);console.log(table.toString());
}
9.2 模块分类功能
// 源码位置:apps/server/src/core/database/database.module.ts
function getEntityModule(entity: EntityMetadata): string {return entity.tableName.startsWith(process.env.DB_TABLE_PREFIX) ? "系统" : "插件";
}
10. 技术特点和最佳实践
10.1 技术特点
- 异步配置: 使用
forRootAsync
支持动态配置 - 环境变量驱动: 所有配置通过环境变量管理
- 自定义日志: 提供详细的数据库操作日志
- 实体自动扫描: 支持多目录实体自动发现
- 模块化设计: 清晰的模块依赖关系
- 初始化服务: 完整的数据库初始化流程
10.2 最佳实践
- 配置分离: 数据库配置与业务逻辑分离
- 错误处理: 完善的错误捕获和日志记录
- 性能监控: 慢查询检测和性能优化
- 安全性: 使用环境变量保护敏感信息
- 可维护性: 清晰的代码结构和注释
11. 配置参数说明
11.1 环境变量配置
变量名 | 类型 | 默认值 | 说明 |
---|---|---|---|
DB_TYPE | string | postgres | 数据库类型 |
DB_HOST | string | - | 数据库主机地址 |
DB_PORT | number | 5432 | 数据库端口 |
DB_USERNAME | string | - | 数据库用户名 |
DB_PASSWORD | string | - | 数据库密码 |
DB_DATABASE | string | - | 数据库名称 |
DB_SYNCHRONIZE | boolean | false | 是否自动同步实体 |
DB_LOGGING | boolean | false | 是否启用日志 |
LOG_DATABASE_SCHEMA | boolean | false | 是否打印实体表格 |
DB_TABLE_PREFIX | string | - | 系统表前缀 |
11.2 TypeORM 配置选项
// 源码位置:apps/server/src/core/database/database.module.ts
{type: "postgres", // 数据库类型host: string, // 主机地址port: number, // 端口号username: string, // 用户名password: string, // 密码database: string, // 数据库名synchronize: boolean, // 自动同步logging: boolean, // 启用日志namingStrategy: SnakeNamingStrategy, // 命名策略logger: CustomLogger, // 自定义日志器entities: string[], // 实体路径
}
12. 启动流程图
13. 总结
DatabaseModule
是 FastbuildAI 后端应用的数据访问层核心,通过 TypeORM 提供了完整的数据库管理功能。该模块具有以下优势:
- 配置灵活: 支持环境变量驱动的动态配置
- 监控完善: 提供详细的数据库操作日志和性能监控
- 初始化完整: 包含完整的数据库初始化和升级流程
- 模块化设计: 清晰的依赖关系和职责分离
- 扩展性强: 支持插件实体和自定义配置
该模块为整个应用提供了稳定可靠的数据持久化基础,是系统架构中的重要组成部分。