Search code examples
typescriptnestjsbackendtypeorm

problem with nestjs/typeorm database selection


Good afternoon nights. I have a problem with selecting a database. I'm working with nestjs and typeorm. Where should I access the atos 2 database and see its records. The problem is that, when I point to it to access it, it reads the first data base instead of the second. I attach the files:

typeorm.config.ts: (Location of my second database)

import { DataSource } from 'typeorm'
import * as dotenv from 'dotenv';
dotenv.config()

export const secondDataSource = new DataSource({
    type: 'mysql',
    host: process.env.DB_HOST2,
    port: parseInt(process.env.DB_PORT2),
    username: process.env.DB_USERNAME2,
    password: process.env.DB_PASSWORD2,
    database: process.env.DB_NAME2,
    synchronize: false,
    dropSchema: false,
    logging: false,
    logger: 'file',
    entities: [
        "./src/*/*/*.entity.ts"
    ],
    migrations:["migrations/*$yarn_config_pruebatestS.ts"]
})

app.module.ts: (Location of my first Database)

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TchiaModule } from './tchia/tchia.module';   
import { TfachisaModule } from './tfachisa/tfachisa.module';

@Module({
  imports: [ConfigModule.forRoot({ isGlobal: true, envFilePath: `.env.${process.env.NODE_ENV}` }),
    TypeOrmModule.forRootAsync({
      imports:[ConfigModule],
      useFactory: (configService: ConfigService) => ({
        type: 'mysql',
        host: configService.get('DB_HOST'),
        port: configService.get('DB_PORT'),
        username: configService.get('DB_USERNAME'),
        password: configService.get('DB_PASSWORD'),
        database: configService.get('DB_NAME'),
        autoLoadEntities: true
      }),
      inject:[ConfigService],
    }),
    TchiaModule,
    TfachisaModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule { }

tfachisa.service.ts: (Location where I want to view the table of my second database)

import { Injectable } from '@nestjs/common';
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { Tfachisa } from './entities/tfachisa.entity';
import { DataSource, Repository } from 'typeorm';
import { secondDataSource } from 'typeorm.config';

@Injectable()
export class TfachisaService {
  constructor(
    @InjectRepository(Tfachisa)
    private readonly tfachisaRepository:Repository<Tfachisa>,
    @InjectDataSource(secondDataSource)
    private readonly seconddataSource: DataSource
  ){}

  async findAll() {
    const data = await this.seconddataSource.query('SELECT * FROM tchia')
    console.log(data)
  }
}


Solution

  • Based on NestJS documentation regarding a few data sources (https://docs.nestjs.com/techniques/database#multiple-databases) you need to:

    UPD:

    If you are using TypeOrmModule.forRootAsync, you have to also set the data source name outside useFactory

    Updated app.module.ts to the correct state. The name field should be in forRootAsync

    1. Import module for second data source

    app.module.ts

    import { Module } from '@nestjs/common';
    import { ConfigModule, ConfigService } from '@nestjs/config';
    import { TypeOrmModule } from '@nestjs/typeorm';
    import { TchiaModule } from './tchia/tchia.module';   
    import { TfachisaModule } from './tfachisa/tfachisa.module';
    
    @Module({
      imports: [ConfigModule.forRoot({ isGlobal: true, envFilePath: `.env.${process.env.NODE_ENV}` }),
        // It will be the default data source
        TypeOrmModule.forRootAsync({
          imports:[ConfigModule],
          useFactory: (configService: ConfigService) => ({
            type: 'mysql',
            host: configService.get('DB_HOST'),
            port: configService.get('DB_PORT'),
            username: configService.get('DB_USERNAME'),
            password: configService.get('DB_PASSWORD'),
            database: configService.get('DB_NAME'),
            autoLoadEntities: true
          }),
          inject:[ConfigService],
        }),
        // It will be the second and named data source ()
        TypeOrmModule.forRootAsync({
          imports:[ConfigModule],
          name: 'secondDataSource'
          useFactory: (configService: ConfigService) => ({
            type: 'mysql',
            host: configService.get('DB_HOST2'),
            port: configService.get('DB_PORT2'),
            username: configService.get('DB_USERNAME2'),
            password: configService.get('DB_PASSWORD2'),
            database: configService.get('DB_NAME2'),
            synchronize: false,
            dropSchema: false,
            logging: false,
            logger: 'file',
            entities: [
               "./src/*/*/*.entity.ts"
            ],
            migrations:["migrations/*$yarn_config_pruebatestS.ts"]
          }),
          inject:[ConfigService],
        }),
        TchiaModule,
        TfachisaModule,
      ],
      controllers: [],
      providers: [],
    })
    export class AppModule { }
    
    1. Import the second data source by name (or you can replace it with the token to don't use 'magic' string)

    tfachisa.service.ts

    import { Injectable } from '@nestjs/common';
    import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
    import { Tfachisa } from './entities/tfachisa.entity';
    import { DataSource, Repository } from 'typeorm';
    
    @Injectable()
    export class TfachisaService {
      constructor(
        @InjectRepository(Tfachisa)
        private readonly tfachisaRepository:Repository<Tfachisa>,
        @InjectDataSource('secondDataSource')
        private readonly seconddataSource: DataSource
      ){}
    
      async findAll() {
        const data = await this.seconddataSource.query('SELECT * FROM tchia')
        console.log(data)
      }
    }
    

    Or you can try to reuse your second data source in this way in app.module.ts:

    TypeOrmModule.forRootAsync({
          imports:[ConfigModule],
          name: 'secondDataSource'
          dataSourceFactory: async () => {
            const dataSource = secondDataSource; // don't forget to import this from typeorm.config.ts
            return dataSource.initialize();
          },
        }),