NestJS启动调用main方法时出现TypeORM Driver not Connected错误
问题:启动时调用数据库操作报错“Driver not Connected”,控制器调用正常
我正在使用NestJS及其集成的TypeORM框架开发程序,依赖版本如下:
"dependencies": { "@nestjs/axios": "^3.0.1", "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.1.1", "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.2.9", "@nestjs/schedule": "^4.0.0", "@nestjs/typeorm": "^10.0.0", "typeorm": "^0.3.9", "typeorm-extension": "^2.1.9" }
主模块app.module.ts声明如下:
@Module({ imports: [ ScheduleModule.forRoot(), ConfigModule.forRoot({ envFilePath: [ '.env.local' ], isGlobal: true, validationSchema: CoreJoi.object({ DB_DATABASE: CoreJoi.string().required(), DB_HOST: CoreJoi.string().required(), DB_PASSWORD: CoreJoi.string().required(), DB_PORT: CoreJoi.number().required().default(5432), DB_SYNCHRONIZE: CoreJoi.boolean().default(false), DB_USERNAME: CoreJoi.string().required(), }), }), DatabaseModule, HttpModule ], providers: [AppService], controllers: [AppController], }) export class AppModule {}
database.module.ts中通过异步函数从Secret Manager获取凭据初始化数据源:
@Module({ imports: [ TypeOrmModule.forRootAsync({ imports: [ ConfigModule ], inject: [ ConfigService ], useFactory: (configService: ConfigService) => ({ type: 'postgres', host: configService.get<string>('DB_HOST'), port: configService.get<number>('DB_PORT'), username: configService.get<string>('DB_USERNAME'), password: async () => { const secretManagerService = new SecretManagerServiceClient(); const [accessResponse] = await secretManagerService.accessSecretVersion({ name: configService.get<string>('DB_PASSWORD'), }); return accessResponse.payload.data.toString(); }, database: configService.get<string>('DB_DATABASE'), synchronize: configService.get<boolean>('DB_SYNCHRONIZE'), autoLoadEntities: true, }), }), TypeOrmModule.forFeature([ /* my entities */ ]), ], providers: [ DatabaseService ], exports: [ DatabaseService ], }) export class DatabaseModule {}
启动服务器时的main.ts代码如下:
async function bootstrap() { const app = await NestFactory.create(AppModule); await app.listen(3000); const appService = app.get(AppService); await appService.process(); await app.close(); } bootstrap();
启动后在需要使用数据库的环节出现以下错误:
throw new TypeORMError("Driver not Connected") ^ TypeORMError: Driver not Connected at PostgresQueryRunner.connect (...) at PostgresQueryRunner.query (...)
但如果通过暴露控制器接口调用appService.process(),例如:
@Post() launchProcessing(): Promise<void> { return this.appService.process(); }
一切运行正常。请问如何解决该问题?我的配置是否存在问题?
解决方案
问题根源
- 密码获取逻辑错误:你在TypeORM配置的
password字段中传入了一个异步函数,但TypeORM的配置解析不会自动处理这个异步函数的返回值,导致数据库初始化时密码未正确获取,连接无法建立。 - 连接未就绪就执行操作:
await app.listen(3000)仅表示NestJS应用启动完成,但TypeORM的数据库连接可能还在异步初始化中,此时直接调用数据库操作会触发未连接错误。而控制器调用时,应用已完全初始化,连接已建立,所以正常运行。
修复步骤
1. 修正数据库密码获取逻辑
将获取Secret Manager密码的异步逻辑移到useFactory函数内部(useFactory本身支持异步),确保返回配置对象前已拿到有效密码:
@Module({ imports: [ TypeOrmModule.forRootAsync({ imports: [ ConfigModule ], inject: [ ConfigService ], // 将useFactory改为异步函数 useFactory: async (configService: ConfigService) => { const secretManagerService = new SecretManagerServiceClient(); // 先获取密码 const [accessResponse] = await secretManagerService.accessSecretVersion({ name: configService.get<string>('DB_PASSWORD'), }); const dbPassword = accessResponse.payload.data.toString(); // 返回完整的数据库配置 return { type: 'postgres', host: configService.get<string>('DB_HOST'), port: configService.get<number>('DB_PORT'), username: configService.get<string>('DB_USERNAME'), password: dbPassword, database: configService.get<string>('DB_DATABASE'), synchronize: configService.get<boolean>('DB_SYNCHRONIZE'), autoLoadEntities: true, }; }, }), TypeOrmModule.forFeature([ /* my entities */ ]), ], providers: [ DatabaseService ], exports: [ DatabaseService ], }) export class DatabaseModule {}
2. 确保数据库连接就绪后再执行操作
在main.ts中手动等待TypeORM的DataSource初始化完成,再调用业务逻辑:
import { DataSource } from 'typeorm'; async function bootstrap() { const app = await NestFactory.create(AppModule); await app.listen(3000); // 等待数据库连接初始化完成 const dataSource = app.get(DataSource); await dataSource.initialize(); const appService = app.get(AppService); await appService.process(); await app.close(); } bootstrap();
通过以上两步,就能保证启动时数据库连接已正确建立,执行appService.process()时不会出现未连接错误。
内容的提问来源于stack exchange,提问作者Yassine Badache
相关产品推荐
相关产品推荐

