-
typeorm 기본 구조 만들기 (3) - repository, service, controller공부하기/node.js 2022. 1. 24. 15:34
app.ts, index.ts에 이어서 기본 entity를 만들어보는 게시글입니다.
기본 구조에서 설명되지 않는 코드는 예제 코드에서 확인하시기 바랍니다~
예제 git : https://github.com/kboysm/typeorm_study1. 예제로 사용될 엔티티를 제작합니다. (User.ts, UserInfo.ts, index.ts)
// src/entity/ User.ts
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn,} from "typeorm";
@Entity("user_info") // 테이블명
export class UserInfo {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: "varchar", length: 150 })
address: string;
@Column({ type: "varchar", length: 25 })
name: string;
@Column()
age: number;
}// src/entity/ UserInfo.ts
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn,} from "typeorm";
@Entity("user_info")
export class UserInfo {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: "varchar", length: 150 })
address: string;
@Column({ type: "varchar", length: 25 })
name: string;
@Column()
age: number;
}// src/entity/index.ts
import { User } from "./User";
import { UserInfo } from "./UserInfo";
export { User, UserInfo };2. EntityRepository를 생성합니다.
// src/repository/UserQueryRepo.ts
import { createQueryBuilder, EntityRepository } from "typeorm";
import { Service } from "typedi";
import { User } from "../entity";
import { PageReq } from "../api/PageReq";
@Service()
@EntityRepository(User)
export class UserQueryRepo {
findAll(param: PageReq) {
return (
createQueryBuilder("user") // 테이블명
.leftJoinAndSelect("User.userInfo", "info") // leftJoinAndSelect("엔티티클래스명.프로퍼티","해당 쿼리에서 사용될 이름")
.skip(param.getOffset())
.take(param.getLimit())
.getManyAndCount() );
}
findOne(id: number) {
return
createQueryBuilder("user")
.where("User.id = :id", { id })
.getOne();
}
// .addSelect("user.password")가 있다는건 비밀번호 비교용 함수, 외부노출 api에 사용금지
findByEmail(email: string) {
return
createQueryBuilder()
.select("user")
.addSelect("user.password")
.from(User, "user")
.where("email = :email", { email })
.getOne();
}
// create(paramObj: UserDto) { // return createQueryBuilder().insert().into(User).values(paramObj).execute(); // }
// update(paramObj: UserDto, id: number) {
// return createQueryBuilder()
// .update(User)
// .set(paramObj)
// .where("id = :id", { id })
// .execute();
//
}
delete(id: number) {
return createQueryBuilder()
.delete()
.from(User)
.where("id = :id", { id })
.execute();
}
}3. service를 제작합니다.
import { Service } from "typedi";
import { InjectRepository } from "typeorm-typedi-extensions";
import { PageReq } from "../api/PageReq";
import { UserQueryRepo } from "../repository/UserQueryRepo";
import { User, UserInfo } from "../entity";
import { UserDto } from "../dto";
import { EntityManager, Transaction, TransactionManager } from "typeorm";
import { PageResList } from "../api/PageResList";
import { PageResObj } from "../api/PageResObj";
@Service()
export class UserService {
constructor( @InjectRepository() readonly userQueryRepo: UserQueryRepo ) {}
async findAll(param: PageReq): Promise<PageResList<User>> {
const result = await this.userQueryRepo.findAll(param);
return new PageResList<User>(
result[1],
param.limit,
result[0].map((el: User) => el),
"User 목록을 찾는데 성공했습니다" );
}
async findOne(id: number): Promise<PageResObj<User>> {
const result: User = await this.userQueryRepo.findOne(id);
return new PageResObj(result, "User를 찾는데 성공했습니다.");
}
@Transaction() async create(
paramObj: UserDto,
@TransactionManager() manager: EntityManager ): Promise<PageResObj<User>> {
const createedUserInfo = await manager.insert(UserInfo, { ...paramObj.userInfo, });
const createedUser = await manager.insert(User, { ...paramObj.getUser, userInfoId: createedUserInfo.identifiers[0].id, });
const result: User = await manager.findOne( User, { id: createedUser.identifiers[0].id }, { relations: ["userInfo"] } );
return new PageResObj(result, "User 생성에 성공했습니다.");
}
@Transaction() async update(
paramObj: UserDto,
id: number,
@TransactionManager() manager: EntityManager ): Promise<PageResObj<User>> {
const oldUser: User = await manager.findOne( User, { id }, { relations: ["userInfo"] } );
if (paramObj.checkExistUser) {
await manager.update(User, { id }, { ...paramObj.getUpdatedUser() });
}
if (paramObj.checkExistUserInfo) {
await manager.update( UserInfo, { id: oldUser.userInfoId }, { ...paramObj.getUpdatedUserInfo() } );
}
const result: User = await manager.findOne( User, { id }, { relations: ["userInfo"] } );
return new PageResObj(result, "User 정보 수정에 성공했습니다.");
}
async delete(id: number) {
const result = await this.userQueryRepo.findOne(id);
const { affected } = await this.userQueryRepo.delete(id);
return new PageResObj( result, affected === 0 ? "User 삭제에 실패했습니다." : "User 삭제에 성공했습니다." ); }
}4. 컨트롤러를 제작합니다
import { UserService } from "../service//UserService"; import { Body, Get, HttpCode, JsonController, Param, Post, QueryParams, Patch, Res, Delete, UseBefore, } from "routing-controllers"; import { Response } from "express"; import { Inject, Service } from "typedi"; import { UserDto } from "../dto"; import { PageReq, PageResObj, PageResList } from "../api"; import { QueryFailedError } from "typeorm"; import { CustomValidation, IdValidation } from "../class/CustomValidation"; @Service() @JsonController("/user") export class UserController { @Inject() userService: UserService; // constructor(private userService: UserService) {} @Get("/findall") public async get(@QueryParams() param: PageReq, @Res() res: Response) { try { return await this.userService.findAll(param); } catch (err) { if (err instanceof QueryFailedError) { console.log("Instance of QueryFailedError!"); return new PageResObj({}, err.message, true); } return new PageResObj({}, err.message, true); } } @Get("/findone/:id") public async getOne(@Param("id") id: number, @Res() res: Response) { const validationResult = new IdValidation(id, "number"); if (!validationResult.result) { return validationResult.getRes(); } try { return await this.userService.findOne(id); } catch (err) { if (err instanceof QueryFailedError) { console.log("Instance of QueryFailedError!"); return new PageResObj({}, err.message, true); } return new PageResObj({}, err.message, true); } } @Post("/create") public async create(@Body() createDto: UserDto, @Res() res: Response) { const validationResult = await new CustomValidation( createDto ).checkValidation(); if (validationResult) return validationResult; try { return await this.userService.create(createDto, null); } catch (err) { if (err instanceof QueryFailedError) { console.log("Instance of QueryFailedError!"); return new PageResObj({}, err.message, true); } return new PageResObj({}, err.message, true); } } @Patch("/update/:id") public async update( @Body() updateDto: UserDto, @Param("id") id: number, @Res() res: Response ) { const validationResult = await new CustomValidation( updateDto ).checkUpdateDtoValidation(); if (validationResult) return validationResult; const idValidationResult = new IdValidation(id, "number"); if (!idValidationResult.result) { return idValidationResult.getRes(); } try { return await this.userService.update(updateDto, id, null); } catch (err) { if (err instanceof QueryFailedError) { console.log("Instance of QueryFailedError!"); return new PageResObj({}, err.message, true); } return new PageResObj({}, err.message, true); } } @Delete("/delete/:id") public async delete(@Param("id") id: number) { const validationResult = new IdValidation(id, "number"); if (!validationResult.result) { return validationResult.getRes(); } try { return await this.userService.delete(id); } catch (err) { if (err instanceof QueryFailedError) { console.log("Instance of QueryFailedError!"); return new PageResObj({}, err.message, true); } return new PageResObj({}, err.message, true); } } }
5. UserDto를 생성합니다. ( src/dto/index.ts )
import { Contains, IsInt, Length, IsEmail, IsFQDN, IsDate, Min, Max, IsString, MinLength, MaxLength, NotContains, ValidateNested, IsEnum, IsNumber, IsUrl, IsBoolean, IsOptional, } from "class-validator"; import { Type } from "class-transformer"; class UserInfoDto { @IsString() address: string; @IsString() name: string; @IsInt() age: number; } class UserDto { @IsEmail() email: string; password: string; @IsOptional() @IsString() userInfoId: string; @ValidateNested({ each: true, message: "userInfo에러" }) @Type(() => UserInfoDto) userInfo: UserInfoDto; // createService get getUser() { return { email: this.email, password: this.password, }; } get checkExistUser() { return this.email || this.password; } get checkExistUserInfo() { return this.userInfo; } // updateService - User getUpdatedUser() { const userKey = ["email", "password"]; const result = {}; userKey.forEach((key) => { if (this[key]) result[key] = this[key]; }); return result; } // updateServuce - UserInfo getUpdatedUserInfo() { const userInfoKey = ["address", "name", "age"]; const result = {}; userInfoKey.forEach((key) => { if (this?.userInfo[key]) result[key] = this?.userInfo[key]; }); return result; } } export { UserDto };
'공부하기 > node.js' 카테고리의 다른 글
typeorm 기본 구조 만들기 (5) - swagger (0) 2022.01.24 typeorm 기본 구조 만들기 (4) - auth,jwt (0) 2022.01.24 typeorm 기본 구조 만들기 (2) - app, index 분리 (0) 2022.01.16 typeorm 기본 구조 만들기 (1) - typeorm 셋팅 (0) 2022.01.16 node.js 기본기 정리 (0) 2020.02.12