하루 종일 삽질한 끝에 TypeORM에 대해 좀 명확하게 이해하게 된 것 같다.
이제 TypeORM CLI로 마이그레이션 할 수 있다!
뿌듯! typeORM cli 마이그레이션으로 생성한 users 테이블!!!
하루 종일 공부하고 삽질해서 얻은 테이블이라 더 기쁘다.
할 것
- TypeORM으로 users 테이블 migration하기
- AWS EC2, RDS 보안설정
- RDS에 API검색용 DB구축
- EC2에 코드 올리기
공부 한 것
1. TypeORM-Relations
relation: typeORM에서 테이블 간의 조인 관계를 나타냄
- one-to-one using
@OneToOne
- many-to-one using
@ManyToOne
- one-to-many using
@OneToMany
- many-to-many using
@ManyToMany
1-1. Relation options
eager: boolean
- If set to true, the relation will always be loaded with the main entity when usingfind*
methods orQueryBuilder
on this entitycascade: boolean | ("insert" | "update" | "remove")[]
- If set to true, the related object will be inserted and updated in the database. You can also specify an array of cascade options.onDelete: "RESTRICT"|"CASCADE"|"SET NULL"
- specifies how foreign key should behave when referenced object is deletedprimary: boolean
- Indicates whether this relation's column will be a primary column or not.nullable: boolean
- Indicates whether this relation's column is nullable or not. By default it is nullable.
1-2. Cascade
import {Entity, PrimaryGeneratedColumn, Column, ManyToMany} from "typeorm";
import {Question} from "./Question";
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(type => Question, question => question.categories)
questions: Question[];
}
import {Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable} from "typeorm";
import {Category} from "./Category";
@Entity()
export class Question {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
text: string;
@ManyToMany(type => Category, category => category.questions, {
cascade: true
})
@JoinTable()
categories: Category[];
}
const category1 = new Category();
category1.name = "animals";
const category2 = new Category();
category2.name = "zoo";
const question = new Question();
question.categories = [category1, category2];
await connection.manager.save(question);
1-3. Cascade Options
cascade옵션은 boolean값이나 cascade 옵션("insert"
, "update"
, "remove"
)을 배열로 넣으면 된다.
relation에서 cascade의 기본 값은 false이다.
@Entity(Post)
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
text: string;
// Full cascades on categories.
@ManyToMany(type => PostCategory, {
cascade: true
})
@JoinTable()
categories: PostCategory[];
// Cascade insert here means if there is a new PostDetails instance set
// on this relation, it will be inserted automatically to the db when you save this Post entity
@ManyToMany(type => PostDetails, details => details.posts, {
cascade: ["insert"]
})
@JoinTable()
details: PostDetails[];
// Cascade update here means if there are changes to an existing PostImage, it
// will be updated automatically to the db when you save this Post entity
@ManyToMany(type => PostImage, image => image.posts, {
cascade: ["update"]
})
@JoinTable()
images: PostImage[];
// Cascade insert & update here means if there are new PostInformation instances
// or an update to an existing one, they will be automatically inserted or updated
// when you save this Post entity
@ManyToMany(type => PostInformation, information => information.posts, {
cascade: ["insert", "update"]
})
@JoinTable()
informations: PostInformation[];
}
1-4. JoinColumn Options
@JoinColumn
not only defines which side of the relation contains the join column with a foreign key, but also allows you to customize join column name and referenced column name.
When we set @JoinColumn
, it automatically creates a column in the database named propertyName + referencedColumnName
.
@ManyToOne(type => Category)
@JoinColumn() // this decorator is optional for @ManyToOne, but required for @OneToOne
category: Category;
This code will create a categoryId
column in the database. If you want to change this name in the database you can specify a custom join column name:
@ManyToOne(type => Category)
@JoinColumn({ name: "cat_id" })
category: Category;
1-5. JoinTable Options
@JoinTable
is used for many-to-many
relations and describes join columns of the "junction" table. A junction table is a special separate table created automatically by TypeORM with columns that refer to the related entities. You can change column names inside junction tables and their referenced columns with @JoinColumn
: You can also change the name of the generated "junction" table.
@ManyToMany(type => Category)
@JoinTable({
name: "question_categories", // table name for the junction table of this relation
joinColumn: {
name: "question",
referencedColumnName: "id"
},
inverseJoinColumn: {
name: "category",
referencedColumnName: "id"
}
})
categories: Category[];
If the destination table has composite primary keys, then an array of properties must be sent to @JoinTable
.
2. TypeORM migration errors
2-1. migration error 1
typeORM cli로 마이그레이션을 하려고 했더니 자꾸 위와 같은 에러가 발생해서 골머리를 앓다가 아래 링크를 통해 해결했다.
찾아보니 typeORM cli에서 entity를 쓰려면 그 entity가 js파일이어야 하는데
typeORM init 시 생성해주는 ormconfig의 entities설정이 .ts로 되어 있어서 해당 에러가 발생하는거였다..
//ormconfig.json
module.exports = {
type: "mysql",
host: "localhost",
port: 3306,
username: "user",
password: "password",
database: "database",
synchronize: true,
logging: false,
entities: ["src/entity/**/*.ts"],
migrations: ["src/migration/**/*.ts"],
cli: {
entitiesDir: "src/entity",
migrationsDir: "src/migration",
subscribersDir: "src/subscriber",
},
};
그래서 위 코드를 아래와 같이 ormconfig에서 접근하는 entity의 위치를 ts빌드 완료 후의 위치로 변경해줬더니 에러를 해결할 수 있었다.
//ormconfig.json
module.exports = {
type: "mysql",
host: "localhost",
port: 3306,
username: "user",
password: "password",
database: "database",
synchronize: true,
logging: false,
entities: ["build/entity/**/*.js"], //수정한 부분
migrations: ["build/migration/**/*.js"], //얘도 js로 바꿔줘야 함
cli: {
entitiesDir: "src/entity",
migrationsDir: "src/migration",
subscribersDir: "src/subscriber",
},
};
후에 보니 공식홈페이지에는 js로 쓰여 있었다....
init 시 자동생성되는 파일에는 왜 ts로 적어둔거야...
+참고사항
ts빌드를 build디렉토리에다가 했기 때문에 entities: ["build/entity/**/*.js"]
라고 해줬지만
ts빌드를 다른 디렉토리에 하지 않거나 빌드하는 디렉토리의 위치가 다르면 수정 내용을 위와 같이 하면 안된다.
//tsconfig.json
{
"compilerOptions": {
"lib": ["es5", "es6"],
"target": "ES2015",
"module": "commonjs",
"strict": true,
"esModuleInterop": false,
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
"moduleResolution": "node",
"outDir": "./build", //ts compile했을때 생기는 js파일을 저장할 디렉토리
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
2-2. migration error 2
위 에러의 해결 방법: 글로벌 typeorm을 사용한다..!
https://github.com/typeorm/typeorm/issues/2450#issuecomment-402005655
글로벌 typeorm을 사용하는 방법
- 주소 직접 입력
$ ./node_modules/.bin/typeorm migration:run
- npx 사용
$ npx typeorm migration:run
1, 2번의 결과는 같다.
3. 기타사항
구글링 하다가 typeORM 공식 github레포의 내용을 검색할 수 있게 만들어 둔 사이트를 발견했다!!
너무좋아!!!!!
'TIL > ChoLog' 카테고리의 다른 글
주니어개발자 앱개발기5 - 4주 프로젝트 회고 (0) | 2020.03.06 |
---|---|
주니어개발자 앱개발기4 - Types + TypeORM 사용하기 (0) | 2020.02.18 |
주니어개발자 앱개발기2 - TS-type, TypeORM-entity (0) | 2020.02.06 |
주니어개발자 앱개발기1 - ChoLog 초록(草錄) (0) | 2020.01.29 |