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

时间:2018-08-23 21:31:33

标签: javascript node.js nestjs typeorm

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

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

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

重点似乎是配置,我正在使用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"
    } ]

错误消息显示:

  

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

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

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

TypeOrmModule.forRoot( { name: "project1" } ),

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

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

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

亲切的问候,
萨格罗伯特

4 个答案:

答案 0 :(得分:3)

我刚刚尝试使用多个数据库和一个ormconfig.json设置TypeORM,但对我来说根本不起作用。它似乎总是使用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' },
  })
]

答案 1 :(得分:0)

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

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

TypeOrmModule.forRootAsync({
  name: DB2_CONNECTION,
  imports: [ConfigModule],
  useClass: TypeormDb2ConfigService,
})

答案 2 :(得分:0)

为清楚起见,并让其他开发人员关注这篇文章:

来自NestJS documentation

  

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

您的一个连接必须具有以下之一:

  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: [...]
})

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

答案 3 :(得分:0)

这就是我设法修复它的方式。使用单个配置文件,我可以在应用程序 boostrap 或使用 TypeOrm 的 CLI 上运行迁移。

src/config/ormconfig.ts

import parseBoolean from '@eturino/ts-parse-boolean';
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import * as dotenv from 'dotenv';
import { join } from 'path';

dotenv.config();

export = [
  {
    //name: 'default',
    type: 'mssql',
    host: process.env.DEFAULT_DB_HOST,
    username: process.env.DEFAULT_DB_USERNAME,
    password: process.env.DEFAULT_DB_PASSWORD,
    database: process.env.DEFAULT_DB_NAME,
    options: {
      instanceName: process.env.DEFAULT_DB_INSTANCE,
      enableArithAbort: false,
    },
    logging: parseBoolean(process.env.DEFAULT_DB_LOGGING),
    dropSchema: false,
    synchronize: false,
    migrationsRun: parseBoolean(process.env.DEFAULT_DB_RUN_MIGRATIONS),
    migrations: [join(__dirname, '..', 'model/migration/*.{ts,js}')],
    cli: {
      migrationsDir: 'src/model/migration',
    },
    entities: [
      join(__dirname, '..', 'model/entity/default/**/*.entity.{ts,js}'),
    ],
  } as TypeOrmModuleOptions,
  {
    name: 'other',
    type: 'mssql',
    host: process.env.OTHER_DB_HOST,
    username: process.env.OTHER_DB_USERNAME,
    password: process.env.OTHER_DB_PASSWORD,
    database: process.env.OTHER_DB_NAME,
    options: {
      instanceName: process.env.OTHER_DB_INSTANCE,
      enableArithAbort: false,
    },
    logging: parseBoolean(process.env.OTHER_DB_LOGGING),
    dropSchema: false,
    synchronize: false,
    migrationsRun: false,
    entities: [],
  } as TypeOrmModuleOptions,
];

src/app.module.ts

import configuration from '@config/configuration';
import validationSchema from '@config/validation';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { LoggerService } from '@shared/logger/logger.service';
import { UsersModule } from '@user/user.module';
import { AppController } from './app.controller';
import ormconfig = require('./config/ormconfig'); //path mapping doesn't work here

@Module({
  imports: [
    ConfigModule.forRoot({
      cache: true,
      isGlobal: true,
      validationSchema: validationSchema,
      load: [configuration],
    }),
    TypeOrmModule.forRoot(ormconfig[0]), //default
    TypeOrmModule.forRoot(ormconfig[1]), //other db
    LoggerService,
    UsersModule,
  ],
  controllers: [AppController],
})
export class AppModule {}

package.json

  "scripts": {
    ...
    "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config ./src/config/ormconfig.ts",
    "typeorm:migration:generate": "npm run typeorm -- migration:generate -n",
    "typeorm:migration:run": "npm run typeorm -- migration:run"
  },

项目结构

src/
├── app.controller.ts
├── app.module.ts
├── config
│   ├── configuration.ts
│   ├── ormconfig.ts
│   └── validation.ts
├── main.ts
├── model
│   ├── entity
│   ├── migration
│   └── repository
├── route
│   └── user
└── shared
    └── logger