NestJS + TypeORM:使用两个或多个数据库?

sag*_*ert 7 javascript node.js typeorm nestjs

自2天以来,我一直在尝试解决此问题,也许我只是在这里遗漏了要点。

我的目标是编写一个NestJS应用程序(包括TypeORM),该应用程序为我的2个或3个小项目提供RestAPI,而不是为其中每个项目都编写一个NestJS-App。

到目前为止,该应用程序已经准备就绪,可以与单个项目(包含其实体,控制器,服务,模块的子文件夹)一起很好地工作,但是我无法使其与所有项目一起运行。

关键似乎是配置,我正在使用ormconfig.json

[ {
    "name": "Project1",
    "type": "mysql",
    "host": "localhost",
    "port": 3306,
    "username": "<username>",
    "password": "<pwd>",
    "database": "<database>",
    "synchronize": false,
    "entities": ["project1/*.entity.ts"],
    "subscribers": ["project1/*.subscriber.ts"],
    "migrations": ["project1/migrations/*.ts"],
    "cli": { "migrationsDir": "project1/migrations" }
}, {
    "name": "project2",
    "type": "mysql",
    "host": "localhost",
    "port": 3306,
    "username": "<another-username>",
    "password": "<another-pwd>",
    "database": "<another-database>",
    "synchronize": false,
    "entities": ["project2/*.entity.ts"],
    "subscribers": ["project2/*.subscriber.ts"],
    "migrations": ["project2/migrations/*.ts"],
    "cli": { "migrationsDir": "project2/migrations"
    } ]
Run Code Online (Sandbox Code Playgroud)

错误消息显示:

[ExceptionHandler]找不到连接默认值,因为它未在任何orm配置文件中定义

当然找不到“默认”,因为我提供了两个配置,它们的唯一名称不同于“默认”。

ApplicationModule中,我可以提供连接的名称,如下所示:

TypeOrmModule.forRoot( { name: "project1" } ),
Run Code Online (Sandbox Code Playgroud)

但是它仅适用于一个项目。

我可以将所有内容混合在一个配置中,但随后我会将所有内容都存储在一个数据库中,所有用户都由同一用户使用,并且可能混合实体...

有人可以给我提示如何解决这个问题吗?也许getConnection(<name>)在每个模块中都有,但是如何启动ApplicationModule呢?

亲切的问候,
sagerobert

Kim*_*ern 17

我只是尝试使用多个数据库和 a 设置 TypeORM,ormconfig.json但它根本不适合我。它似乎总是使用default连接,当没有找到默认(= 没有显式名称)连接时,它会抛出相应的错误。

但是当我在中定义连接时它确实有效app.module.ts(我删除了ormconfig.json):

imports: [
  ...,
  TypeOrmModule.forRoot({
    name: 'Project1',
    type: 'mysql',
    host: 'localhost',
    port: 3306,
    username: '<username>',
    password: '<pwd>',
    database: '<database>',
    synchronize: false,
    entities: ['project1/*.entity.ts'],
    subscribers: ['project1/*.subscriber.ts'],
    migrations: ['project1/migrations/*.ts'],
    cli: { migrationsDir: 'project1/migrations' },
  }),
  TypeOrmModule.forRoot({
    name: 'project2',
    type: 'mysql',
    host: 'localhost',
    port: 3306,
    username: '<another-username>',
    password: '<another-pwd>',
    database: '<another-database>',
    synchronize: false,
    entities: ['project2/*.entity.ts'],
    subscribers: ['project2/*.subscriber.ts'],
    migrations: ['project2/migrations/*.ts'],
    cli: { migrationsDir: 'project2/migrations' },
  })
]
Run Code Online (Sandbox Code Playgroud)

  • @SorayaAnvari当您使用`forFeature`导入时,您是否还传递了连接的`name`:`TypeOrmModule.forFeature([Album], 'albumsConnection')`? (3认同)

o.N*_*sie 8

为了清楚起见并让其他开发人员来到这篇文章:

NestJS 文档

如果您没有为连接设置任何名称,则其名称将设置为默认值。请注意,您不应该有多个没有名称或名称相同的连接,否则它们只会被覆盖。

您的连接之一必须具有以下其中一项:

  1. "name":"default"
  2. 没有任何名字。

我建议在其中声明所有连接,ormconfig.json而不是在代码中声明它。

ormconfig.json以下导入连接的示例:

@Module({
    imports: [TypeOrmModule.forFeature([Entity1, Entity2]), //This will use default connection
    TypeOrmModule.forRoot({name: 'con1'}), // This will register globaly con1
    TypeOrmModule.forRoot({name: 'con2'}), // This will register globaly con2
    controllers: [...],
    providers: [...],
    exports: [...]
})
Run Code Online (Sandbox Code Playgroud)

在您的模块中(不必是根模块,只有您需要连接的模块)。


Dam*_*wen 8

对于那些面临这个问题的人,这是我的解决方案

应用程序模块

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [
        database,
        databaseAllo #<= my second database
      ]
    }),
    TypeOrmModule.forRootAsync({
      useFactory: (configs: ConfigService) => configs.get("db_config"),
      inject: [ConfigService],
    }),
    TypeOrmModule.forRootAsync({
      name:"db_allo", #<= create connection to my second db
      useFactory: (configs: ConfigService) => configs.get("db_config_allo"),
      inject: [ConfigService],
    }),
    AuthModule,
    JwtAuthModule
  ],
  controllers: []
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)

我的项目模块(包含第二个数据库的表)


@Module({
  imports: [
    TypeOrmModule.forFeature([AlloMpcTable], "db_allo" #<= call connection again),
  ],
  providers: [
    AlloRepository
  ],
  exports: [AlloRepository],
  controllers: [],
})
export class AlloModule {}
Run Code Online (Sandbox Code Playgroud)

我的项目存储库


@Injectable()
export class AlloRepository extends BaseRepository<AlloMpcTable> {
  constructor(
    @InjectRepository(AlloMpcTable, "db_allo") #<= you need to call connection again
    private readonly allo: Repository<AlloMpcTable>,
  ) {
    super(allo)
  }

  public async Find(id: number): Promise<AlloMpcTable> {
    return await this.allo.findOne(id)
  }

}
Run Code Online (Sandbox Code Playgroud)


Fro*_*nex 5

您需要在TypeOrmModule.forRoot({ name: 'db1Connection' }) 中显式传递同一级别的连接名称,以防您使用多个数据库连接。

TypeOrmModule.forRootAsync({
  name: DB1_CONNECTION,
  imports: [ConfigModule],
  useClass: TypeormDb1ConfigService,
}),

TypeOrmModule.forRootAsync({
  name: DB2_CONNECTION,
  imports: [ConfigModule],
  useClass: TypeormDb2ConfigService,
})
Run Code Online (Sandbox Code Playgroud)

  • 先生,你刚刚救了我的命。`TypeOrmModule.forRootAsync` 具有我见过的最糟糕的 API 接口。 (2认同)