일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- springboot
- maven
- MariaDB
- 서브라임 텍스트
- HTML Special Entity
- NestJS
- PostgreSQL
- orioledb
- graph database
- OGM
- Spring Boot
- Java
- Spring Cloud
- NextJs
- PG-Strom
- Maven Project
- loadcomplete
- Can't load AMD 64-bit .dll on a IA 32-bit platform
- Next.js
- JSP
- tortoise SVN
- Windows 10
- typeorm
- exit code = -805306369
- tomcat
- HTML Code
- Eclipse
- STS
- Spring
- BRIN
- Today
- Total
Undergoing
02. Nest - PostgreSQL 연동 본문
1. TypeORM
- Object-Relational Mapping
- 객체와 RDB의 data를 자동으로 매핑해줌
- TypeScript와 함께 선호되는 기법 중 하나
2. TypeORM 설치
D:\IdeaProjects\nest-app>npm install @nestjs/typeorm typeorm pg
...
+ @nestjs/typeorm@8.0.2
+ pg@8.7.1
+ typeorm@0.2.36
added 54 packages from 93 contributors and audited 880 packages in 15.802s
84 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
D:\IdeaProjects\nest-app>npm install ts-node -g
...
+ ts-node@10.1.0
added 13 packages from 44 contributors in 1.175s
3. DB 연결
공식 가이드 문서에서는 다음과 같이 두 가지 기법으로 연결 방법을 제시함
- app.module.ts에 직접 연동
- root에 ormconfig.json 파일을 만들어 작성
나는 소스 관리 차원에서 후자를 택함
// ormconfig.json
{
"type": "postgres",
"host": "localhost",
"port": 5432,
"username": "test",
"password": "test",
"database": "test",
"entities": ["dist/**/*.entity{.ts,.js}"],
"synchronize": true
}
* synchronize: true 설정은 production data가 손상될 수 있으니 production mode에서는 사용해서는 안 된다고 함
이후 app.module.ts에 관련 설정 추가
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TestModule } from './test/test.module';
import {Connection} from "typeorm";
@Module({
imports: [TypeOrmModule.forRoot(), TestModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
constructor(private readonly connection: Connection) {}
}
* connection은 지금 단계에서는 필요하지 않아 보이지만 일단 넣어두고 쓰임새는 나중에 파악하기로 함
상기 forRoot를 통해 객체를 전달할 수 있음. app.module.ts에서 ormconfig.json의 내용을 관리하려 한다면 이런 모양이 될 것
// app.module.ts
...
@Module({
...
imports: [
TypeOrmModule.forRoot({
type: "postgres",
host: "localhost",
port: 5432,
username: "test",
password: "test",
database: "test",
entities: ["dist/**/*.entity{.ts,.js}"],
synchronize: true
}),
],
...
})
export class AppModule {}
* entity의 경로가 dist인 이유는 build 시 typescript 형태의 파일이 해당 경로에서 js파일로 recomplie 되어 node에서 읽어서 처리할 수 있게 됨. package.json 및 tsconfig.json 등에서 module param을 moulde로 처리하는 방법도 있는 것 같은데 우선 현재 기준에서 이해할 수 있는 구조로 가기로 함.
3. Test
TypeORM은 저장소 디자인 패턴을 지원, 각 항목에 자체 저장소가 존재함. 이 저장소는 db 연결에서 획득할 수 있음
커스텀해서 해보려 하다가 이왕에 처음부터 제대로 해보자는 생각에 관련 튜토리얼을 따라해보는 것부터 시작하려 함
우선 다음과 같은 구조 및 파일 생성함
src
└ test
├ dto
│ └ create-test.dto.ts
├ test.controller.ts
├ test.entity.ts
├ test.module.ts
├ test.repository.ts
└ test.service.ts
- create-test.dto.ts : table 생성 관련 dto. DB는 만들어져 있는 환경에서 테스트하느라 이 dto는 만들어두고 사용하지는 않음.
import { IsNotEmpty } from 'class-validator'; // data 전송 시 해당 field의 유효성을 검사하는 lib
export class CreateUserDto {
@IsNotEmpty()
readonly first_name: string;
@IsNotEmpty()
readonly last_name: string;
@IsNotEmpty()
readonly usr_id: string;
@IsNotEmpty()
readonly secret: string;
}
- test.controller.ts
import { Controller, Get, Param, Query, Req } from '@nestjs/common';
import { TestService } from './test.service';
import { TestEntity } from './test.entity';
@Controller('test')
export class TestController {
constructor(private readonly testService: TestService) {}
@Get('/findName')
async findName(
@Query('first_name') first_name: string,
@Query('last_name') last_name: string,
): Promise<TestEntity[]> {
const ret = this.testService.findName(first_name, last_name);
return ret;
}
}
- test.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, BeforeInsert } from 'typeorm';
@Object
@Entity({name:"tb_user", schema:"public"})
export class TestEntity {
@PrimaryGeneratedColumn() // 이 Annotation을 통해 기본키로 사용함을 명시함
id: string;
@Column()
company_name: string;
@Column({ nullable: false })
first_name: string;
@Column({ nullable: false })
last_name: string;
@Column({ nullable: false })
secret: string;
@Column({ nullable: false })
usr_id: string;
}
* entity annotation에 대해서는 몇 가지 옵션이 존재하는데, name이나 schema 옵션을 부여하면 해당 entity의 활용처를 명시적으로 지정할 수 있다. 차후 이를 잘 활용하면 모델단이 필요 이상으로 지저분해질 일이 없을 것 같다.
import { OrderByCondition } from "../../find-options/OrderByCondition";
/**
* Describes all entity's options.
*/
export interface EntityOptions {
/**
* Table name.
* If not specified then naming strategy will generate table name from entity name.
*/
name?: string;
/**
* Specifies a default order by used for queries from this table when no explicit order by is specified.
*/
orderBy?: OrderByCondition | ((object: any) => OrderByCondition | any);
/**
* Table's database engine type (like "InnoDB", "MyISAM", etc).
* It is used only during table creation.
* If you update this value and table is already created, it will not change table's engine type.
* Note that not all databases support this option.
*/
engine?: string;
/**
* Database name. Used in Mysql and Sql Server.
*/
database?: string;
/**
* Schema name. Used in Postgres and Sql Server.
*/
schema?: string;
/**
* Indicates if schema synchronization is enabled or disabled for this entity.
* If it will be set to false then schema sync will and migrations ignore this entity.
* By default schema synchronization is enabled for all entities.
*/
synchronize?: boolean;
/**
* If set to 'true' this option disables Sqlite's default behaviour of secretly creating
* an integer primary key column named 'rowid' on table creation.
* @see https://www.sqlite.org/withoutrowid.html.
*/
withoutRowid?: boolean;
}
- test.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TestController } from './test.controller';
import { TestService } from './test.service';
import { TestEntity } from './test.entity';
@Module({
imports: [TypeOrmModule.forFeature([TestEntity])],
exports: [TypeOrmModule],
providers: [TestService],
controllers: [TestController],
})
export class TestModule {}
- test.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm/dist/common/typeorm.decorators';
import { Repository } from 'typeorm/repository/Repository';
import { TestEntity } from './test.entity';
@Injectable()
export class TestService {
constructor(
@InjectRepository(TestEntity)
private readonly testRepository: Repository<TestEntity>,
) {}
findName(first_name: string, last_name: string): Promise<TestEntity[]> {
console.log("name : " + first_name + " " + last_name);
return this.testRepository.find({
where: { first_name, last_name },
});
//console.log(Logger.log(""));
//return found;
}
}
* 기본적인 검색어는 Query Annotation으로 파라미터 처리하고, 서비스단에서 바로 리턴
find 구문 내에 상기 코드와 같이 할 경우 SELECT * 가 되지만, select : ["column1", column2", ...] 를 통해 필요 컬럼만 return 받을 수도 있다.
TypeORM의 Repository 외에, 해당 쿼리용 Repository 파일을 만들어 처리하는 방식도 있는데, 이는 아직 이해가 제대로 안 되어 공통 Repository로 처리함
'개발 > Web Development' 카테고리의 다른 글
03. Next.js 붓기 (0) | 2021.08.12 |
---|---|
01. Nest (0) | 2021.08.04 |
[AngularJS] 기본 개발 환경 세팅 (0) | 2017.06.22 |
[jqgrid] loadcomplete를 이용하여 검색 결과 처리 (0) | 2015.03.13 |
[Spring] @ResponseBody 리턴 시 한글 깨짐 문제 (1) | 2014.11.26 |