[NestJS] - 17. TypeORM에 여러개의 데이터베이스 연결하여 사용하기

2023. 2. 25. 13:43
반응형

 

실무에서 Application의 개발 혹은 유지보수를 하다보면, 다른 데이터베이스를 추가적으로 사용해야 하거나, 타 업체의 데이터베이스를 제공받아서 사용해야 하는 일이 생긴다. 지금까지는 데이터베이스 1개를 연결하는 것을 해보았는데, 이번에는 데이터베이스 여러개를 연결해보는 작업을 한번 해보자.

 

 

 


Module

 

 app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ProductsModule } from './apis/products/products.module';
import { ProductCategoryModule } from './apis/productsCategory/productCategory.module';

@Module({
  imports: [
    //ORM : Database Connection
    TypeOrmModule.forRoot({
      //name: 'default',
      type: 'mariadb',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '1111',
      database: 'my-database',
      entities: [__dirname + '/apis/**/*.entity.*'],
      synchronize: true,
      logging: true,
    }),
    TypeOrmModule.forRoot({
      name: 'secondDB',
      type: 'mariadb',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: '1111',
      database: 'my-database2',
      entities: [__dirname + '/apis/**/*.entity.*'],
      synchronize: true,
      logging: true,
    }),
    ProductsModule,
    ProductCategoryModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

 

  • imports에 TypeOrmModule.forRoot()를 추가로 작성한다. 
  • 다른점은 name을 반드시 작성해주어야 한다. 이제 앞으로 name은 dataSource Name으로 사용될 것이며, 맨 처음 데이터베이스처럼 name을 지정해주지 않으면 디폴트 데이터베이스로 사용되게 된다.

 

 

 

 


Entity

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity({
  database: 'my-database2',
})
export class Board {
  @PrimaryGeneratedColumn('increment')
  id: number;

  @Column()
  title: string;

  @Column()
  contents: string;
}

 

  • 디폴트 데이터베이스가 아닌 다른 데이터베이스의 엔티티 모델을 생성하려 할 때에는 @Entity에 사용할 데이터베이스 이름을 기재해주자. 
  • 이름을 기재하지 않으면 디폴트 데이터베이스의 엔티티로 인식하게 된다.

 

 


Module / Service

 

@Module({
  imports: [
    TypeOrmModule.forFeature([ProductCategory]),
    TypeOrmModule.forFeature([Board], 'secondDB'),
  ],
  controllers: [ProductCategoryController],
  providers: [ProductCategoryService],
})
export class ProductCategoryModule {
  //
}

 

  • 모듈에는 디폴트 데이터베이스가 아닌 데이터베이스는 DataSource Name을 옵션에 추가해서 imports시켜주면 된다.

 

 

@Injectable()
export class ProductCategoryService {
  constructor(
    @InjectRepository(ProductCategory)
    private readonly productCategoryRepository: Repository<ProductCategory>, //DB Connection 객체, Generic을 지정해주어야함

    @InjectRepository(Board, 'secondDB')
    private readonly boardRepository: Repository<Board>,

    private readonly connection: Connection, 

    @InjectDataSource('secondDB')
    private readonly connection2: Connection, 
  ) {}
  
}

 

  • 서비스의 Repository 주입도 마찬가지로 DataSource Name을 옵션에 추가해서 InjectRepository() 해주면 된다. 
  • Connection 객체는 @InjectDataSource(DataSource Name) 데코레이터를 통해서 디폴트 데이터베이스가 아닌 Connection 객체를 생성해 줄 수 있다.

 

 

  async selectOne() {
    const queryRunner = await this.connection2.createQueryRunner();
    try {
      await queryRunner.connect();
	  //...

      //Respository
      const repoResult = await this.boardRepository.findOne({
         where: {id: 1}
      });
      
      //QueryBuilder
      const queryBuilderResult = await queryRunner.manager
        .createQueryBuilder(Board, 'b')
        .where('b.id = :id', { id: 1 })
        .getOne();
        
      //RawQuery
      const rawQueryRes = await queryRunner.manager.query(
        `select * from board where id = ?`,
        [1],
      );

      //...
    } catch (e) {
      // ...
    } finally {
      // ...
    }
  }

 

  • Repository나 QueryBuilder도 똑같이 사용해 주는 것이 가능하다.
  • Connection 객체를 이용할 때에는 참조하는 Data Source에 따른 Connection을 구분하여 사용하면 된다.

 

 


지금 포스팅한 방식으로 TypeORM에서 여러개의 데이터베이스를 연결하여 사용하는 방법까지 알아보았다.

다음 포스팅에서는 인증에 대해서 다루어보겠다.

 

 

 

반응형

BELATED ARTICLES

more