[nest.js] Custom Repository
nest.js typeorm 0.2.x 까지는 @EntityRepository 데코레이터를 사용해서 쉽게 주입이 가능해 졌으나 0.3.x 로 올라가면서 deprecated 되었다. 아무래도 deprecated 된 건 꺼림칙하다.
custom repository를 포기하는건 거의 실무에선 불가에 가까운데 다행히도 기존처럼 사용 가능하다.
본인도 nest.js를 한지 한달도 안된 상태라 깊게는 모르므로 간략히 이해가는 선에서 정리한다.
필요한 파일과 개념
- decorator
자바의 annotation. 주입에 필요한 파일이다. module 에서 동적으로 import 하기 위한 준비물 - module
nest.js 에는 필수로 module 이라는 정의서가 필요하다. c++로 치자면 헤더같은 존재로 사용하는 controller와 service에서 필요한 라이브러리들을 미리 정의한 파일이다. module 을 통해 주입이 가능해 지므로 필수 지식이다. - custom repository
repository 를 상속받아 구현한 클래스. 자바의 mybatis xml 이라고 보면 된다.
query builder를 통한 db 로직이 들어간다.
실제 소스코드 예
decorator
import { SetMetadata } from "@nestjs/common";
// import { BaseEntity } from "typeorm";
export const TYPEORM_EX_CUSTOM_REPOSITORY = 'TYPEORM_EX_CUSTOM_REPOSITORY ';
export function CustomRepository( entity : Function ) : ClassDecorator
{
return SetMetadata( TYPEORM_EX_CUSTOM_REPOSITORY , entity );
}
module
import { DynamicModule, Provider } from "@nestjs/common";
import { TYPEORM_EX_CUSTOM_REPOSITORY } from "./typeorm-ex.decorator";
import { getDataSourceToken } from "@nestjs/typeorm";
import { DataSource } from "typeorm";
export class TypeormExModule
{
public static forCustomRepository<T extends new ( ...args : any[] ) => any>( repositories : T[] ) : DynamicModule
{
const providers : Provider[] = [];
let entity;
for ( const repository of repositories )
{
entity = Reflect.getMetadata( TYPEORM_EX_CUSTOM_REPOSITORY, repository );
if ( !entity )
continue;
providers.push(
{
inject : [getDataSourceToken()],
provide : repository,
useFactory : ( dataSource : DataSource ) : typeof repository =>
{
const baseRepository = dataSource.getRepository<any>( entity );
return new repository( baseRepository.target, baseRepository.manager, baseRepository.queryRunner );
}
}
);
}
return {
exports : providers,
module : TypeormExModule,
providers
};
}
}
custom repository
import { Repository } from "typeorm";
import { Board } from "./board.entity";
import { CustomRepository } from "./typeorm-ex.decorator";
@CustomRepository(Board)
export class BoardRepository extends Repository<Board>
{
async findAllByAuthorID( authorid : string ) : Promise<Board[]>
{
return await this.createQueryBuilder( 'board' )
.where( 'userId = :userId', { userId : authorid } )
.getMany();
}
}
service 에서 생성자에 custom repository 를 선언하고 사용
참조