NestJS ⚡ Настройка нескольких БД с помощью TypeORM


Введение

Привет, в этом посте я опишу, как настроить и использовать несколько соединений с базами данных на простом примере.

Документация NestJS по большей части великолепна, но в ней есть некоторые важные упущения в разделе о множественных базах данных.

Я буду исходить из того, что вы уже создали приложение NestJS и настроили 2 или более баз данных и готовы к подключению. Давайте сразу перейдем к делу.

Давайте перейдем к делу

Определите параметры подключения к БД

Следуя документации NestJS, мы найдем пример опций подключения, которые можно задать непосредственно в коде.

...
@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      entities: [Customer],
      synchronize: true,
    }),
  ],
})
...
Войти в полноэкранный режим Выйти из полноэкранного режима

Вместо того чтобы выставлять учетные данные непосредственно в коде, мы должны использовать файл конфигурации окружения или аналогичную стратегию.

В данном примере мы воспользуемся пакетом @nestjs/config для получения учетных данных базы данных из файла окружения. Более подробную информацию о том, как установить и использовать пакет config, можно найти в NestJS Configuration Docs. Это простой процесс.

...
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => {
        return {
          type: 'mssql',
          host: configService.get('MAIN_DB_HOST'),
          port: parseInt(configService.get('MAIN_DB_PORT')),
          database: configService.get('MAIN_DB_DATABASE'),
          username: configService.get('MAIN_DB_USERNAME'),
          password: configService.get('MAIN_DB_PASSWORD'),
          schema: configService.get('MAIN_DB_SCHEMA'),
          entities: [Customer],
          synchronize: false,
        };
      },
    }),
...
Вход в полноэкранный режим Выход из полноэкранного режима

Нам не нужно определять имя соединения для нашего первого соединения. По умолчанию оно будет называться ‘default’ 😬. Для всех остальных определенных соединений нам нужно будет задать имя.

В документации NestJS сказано, что свойство name должно быть добавлено внутри объекта options, на том же уровне, что и host, port и т.д.

...
@Module({
  imports: [
    TypeOrmModule.forRoot({
      ...defaultOptions,
      host: 'user_db_host',
      entities: [User],
    }),
    TypeOrmModule.forRoot({
      ...defaultOptions,
      name: 'albumsConnection',
      host: 'album_db_host',
      entities: [Album],
    }),
  ],
})
...
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь, поскольку мы получаем наши учетные данные из файла .env и используем forRootAsync, нам нужно добавить свойство connection name вне функции useFactory 👀. Это действительно важная деталь, которая не упоминается нигде в документации.

Окончательный файл app.module.ts должен выглядеть следующим образом.

Сущности

Для этого упражнения мы создали две сущности. Сущность Customer будет использовать основное соединение с базой данных, а сущность AccessLog будет использовать вторичное соединение с базой данных. Для получения дополнительной информации о сущностях TypeOrm и шаблоне репозитория ознакомьтесь с NestJS TypeOrm Docs и TypeOrm Docs.

Использование основного подключения к БД

Чтобы получить доступ к функциональности TypeOrm сущности Customer, нам нужно импортировать TypeOrm в модуль Customer.

И вот как мы используем его в сервисе Customer.

Использование вторичного подключения к БД

Как и для основного подключения и сущности Customer, нам нужно импортировать TypeOrm в модуль AccessLog, но на этот раз нам также нужно передать имя подключения в метод TypeOrmModule.forFeature([Entities, ...], connectionName).

И вот как мы используем его в службе AccessLog.

Заключение

✅ Нам удалось настроить конфигурацию с несколькими базами данных со значениями учетных данных из файла окружения.
✅ Определили, какое соединение должна использовать каждая сущность.
✅ Зная, как добавить вторичное соединение, мы сможем добавить много других соединений по мере необходимости.
✅ Узнали о небольших проблемах при асинхронной инициализации TypeOrm.

Я очень надеюсь, что эта статья была полезной.

Если у вас есть замечания или вы нашли ошибки, пожалуйста, свяжитесь со мной.

Оцените статью
Procodings.ru
Добавить комментарий