You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中TypeORM v0.3.0自定义装饰器如何获取当前数据库连接

NestJS 框架下 TypeORM v0.3+ 外部脚本获取数据库连接方案

TypeORM v0.3 版本彻底移除了getManager()、getConnection()这类全局静态方法,所有数据库连接实例统一由DataSource类管理,原有全局静态查找连接的逻辑失效,才会抛出ConnectionNotFoundError: Connection default was not found错误。

由于class-validator的自定义验证装饰器运行在NestJS依赖注入容器上下文之外,无法直接通过构造器注入获取实例,需要通过持有全局DataSource引用的方式实现访问,具体步骤如下:

步骤1:创建DataSource持有工具

新建一个全局可导入的文件,用来保存初始化完成的DataSource实例,避免重复创建连接:

// src/common/database/datasource.holder.ts
import { DataSource } from 'typeorm';

let activeDataSource: DataSource | null = null;

/**
 * 保存初始化完成的DataSource实例,仅在应用启动时调用
 */
export const setGlobalDataSource = (ds: DataSource) => {
  activeDataSource = ds;
};

/**
 * 获取当前活跃的数据库连接实例
 */
export const getGlobalDataSource = (): DataSource => {
  if (!activeDataSource) {
    throw new Error('DataSource 未完成初始化,请确认应用启动完成后再调用');
  }
  return activeDataSource;
};

步骤2:应用启动时存入DataSource实例

两种实现方式选其一即可:

方式A:main.ts启动后赋值(单连接场景推荐)

在Nest应用启动完成后,直接从应用容器取出DataSource实例存入持有器,不需要修改原有TypeORM配置:

// src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DataSource } from 'typeorm';
import { setGlobalDataSource } from './common/database/datasource.holder';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 从Nest容器取出已经初始化完成的DataSource实例
  const dataSource = app.get(DataSource);
  setGlobalDataSource(dataSource);
  
  await app.listen(3000);
}
bootstrap();

方式B:TypeORM初始化时赋值(多连接场景推荐)

在TypeORM根模块的dataSourceFactory中完成实例赋值,可以精确控制不同连接的持有逻辑:

// src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';
import { setGlobalDataSource } from './common/database/datasource.holder';

@Module({
  imports: [
    TypeOrmModule.forRootAsync({
      useFactory: () => ({
        type: 'mysql', // 替换为你实际使用的数据库类型
        host: process.env.DB_HOST,
        port: Number(process.env.DB_PORT),
        username: process.env.DB_USER,
        password: process.env.DB_PASS,
        database: process.env.DB_NAME,
        entities: [__dirname + '/**/*.entity{.ts,.js}'],
        synchronize: false,
      }),
      dataSourceFactory: async (options) => {
        const dataSource = await new DataSource(options).initialize();
        setGlobalDataSource(dataSource);
        return dataSource;
      },
    }),
  ],
})
export class AppModule {}

步骤3:验证装饰器中替换原有逻辑

在自定义验证装饰器中,直接导入getGlobalDataSource方法获取实例,替换原有getManager()的写法即可:

import { getGlobalDataSource } from '../common/database/datasource.holder';

// 验证装饰器内部的数据库查询逻辑
const manager = getGlobalDataSource().manager;
return manager.count(entity, {
  ...where,
}).then((count) => count < 1);

注意事项

  • 不要在应用启动阶段(比如模块加载的顶层代码中)调用getGlobalDataSource(),此时DataSource还未完成初始化会抛出错误;验证装饰器的逻辑是在请求进入时执行,此时应用已经启动完成,不存在时序问题
  • 多数据库连接场景下,可以在持有器中用Map按连接名称存储不同的DataSource实例,按需获取
  • 不要手动重复new DataSource()创建实例,必须使用NestJS TypeORM模块初始化完成的实例,否则会产生多余的数据库连接,造成资源泄漏

内容的提问来源于stack exchange,提问作者Dacxj0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 01:03:24