启动数据库postgresql
- 创建数据目录(Winodws Toolbox不用做这一步)
- 在项目目录创建blog-data目录
- .gitignore里添加/blog-data/
启动PostgreSQL
一句命令启动pg:
docker run -v "$PWD/blog-data":/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_USER=blog -e POSTGRES_HOST_AUTH_METHOD=trust -d postgres:12.2
以下是 Windows 旧版 Docker 客户端(Toolbox)的命令(推荐 Windows 用户使用这一版客户端,很稳)
docker run -v "blog-data":/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_USER=blog -e POSTGRES_HOST_AUTH_METHOD=trust -d postgres:12.2
$ docker ps -a查看容器运行状态


如果需要密码,可以在docker run 选项中
-e POSTGRES_HOST_AUTH_ME THOD=trust替换成
-e POSTGRES_PASSWORD=123456执行pg命令
\l 用于 list databases,目前有一个blog数据库

- \c 用于 connect to a database

- \dt 用于 display tables,目前没有tables

创建数据库
用SQL来创建数据库
- 因为TypeORM没有单纯提供创建数据库的API
$ CREATE DATABASE xxx ENCODING 'UTF8' LC_COLLATE 'en_US.utf8' LC_CTYPE 'en_US.utf8';- xxx换成表名
- 我们需要创建三个数据库:开发、测试、生产
- 对应英文:Development、test、production
- 最终结果得到三个数据库


安装TypeORM
步骤
打开官网,点击Getting Started
$ yarn add typeorm$ yarn add reflect-metadata$ yarn add --dev @types/node$ yarn add pg配置tsconfig.json
"emitDecoratorMetadata": true,"experimentalDecorators": true,
这时候先 git commit一下,非常重要
$ ./node_modules/.bin/typeorm init --database postgres
或者
$ npx typeorm init --database postgres


- 这个命令会覆盖很多东西,撤销一部分
$ git checkout HEAD -- .gitignore撤销对.gitiggnore 的修改$ git checkout HEAD -- package.json撤销对package.json的修改$ git checkout HEAD -- tsconfig.json撤销对tsconfig.json的修改修改ormconfig.json的内容
{"type": "postgres","host": "localhost",// 如果是toolbox用户,输入 docker-machine.exe ip// 将这里修改为ip"port": 5432,"username": "blog","password": "","database": "blog_development","synchronize": true,"logging": false,"entities": ["src/entity/**/*.ts"],"migrations": ["src/migration/**/*.ts"],"subscribers": ["src/subscriber/**/*.ts"],"cli": {"entitiesDir": "src/entity","migrationsDir": "src/migration","subscribersDir": "src/subscriber"}}
User.ts中会报错

- 如果在tsconfig.json中关闭严格模式就不会报错

- 删掉/src/index.ts中的内容 ```json import “reflect-metadata”; import { createConnection } from “typeorm”;
createConnection().then(async connection => {
console.log(connection)connection.close()
}).catch(error => console.log(error));
<a name="lmGnN"></a># 运行index.ts<a name="txZ6K"></a>## 如何运行TypeScript- Next.js默认使用babel来将TS编译为JS(内置功能)- TypeORM推介使用ts-node来编译(没有内置)- babel和ts-node对TS的支持并非完全一致- 统一,全都用babel<a name="eTv2l"></a>## 连接数据库`$ yarn add @babel/cli`<br />`$ yarn add --dev @babel/plugin-proposal-decorators`<br />创建.babelrc```json{"presets": ["next/babel"],"plugins": [["@babel/plugin-proposal-decorators",{"legacy": true}]]}
$ npx babel ./src --out-dir dist --extensions ".ts,.tsx"
- 修改ormconfig.json的内容 “entities”: [“dist/entity/*/.js”]
- 删除dist,删掉/src/entity/User.ts
- 重新babel
$ node dist/index.js
禁用sync
ormconfig.json
- “synchronize”: true => false
- 如果true,那么在连接数据库时,typeorm会自动根据entity目录来修改数据表
假设entity里面有User,就会自动创建User表
看起来方便但是sync可能会在我们修改User时删除数据
- 绝不要在生产环境使用sync
通过migration创建表
posts表
$ npx typeorm migration:create -n CreatePost
得到src/migration/{TIMESTAMP}-CreatePosts.ts
import { MigrationInterface, QueryRunner, Table } from "typeorm";export class CreatePost1626854000792 implements MigrationInterface {public async up(queryRunner: QueryRunner): Promise<void> {//升级数据库return await queryRunner.createTable(new Table({name: 'posts',columns: [{name: 'id',type: 'int',isPrimary: true,isGenerated: true,generationStrategy: 'increment'}, {name: 'title',type: 'varchar'}, {name: 'content',type: 'text'}]}))}public async down(queryRunner: QueryRunner): Promise<void> {//降级数据库return await queryRunner.dropTable('posts')}}
- 用babel编译成js
$ npx babel ./src --out-dir dist --extensions ".ts,.tsx"
- 修改ormconfig.json的内容 “migrations”: [“dist/migration/*/.js”],
- 重新babel编译
- 运行
$ typeorm migration:run
- 如果表设计错了,这时候就可以降级,package.json中加个命令

$ typeorm migration:revert
- 为了不每次运行babel,可以将package.json中的命令改为
“typeorm:build”: “babel -w ./src —out-dir dist —extensions .ts,.tsx”,
同时也可以加入到dev中,把两个命令写到一起
$ typeorm entity:create -n Post

- /src/entity/Post.ts ```json import { Column, Entity, PrimaryGeneratedColumn } from ‘typeorm’;
@Entity(‘posts’) export class Post { @PrimaryGeneratedColumn(‘increment’) id: number; @Column(‘varchar’) title: string; @Column(‘text’) content: string
}
<a name="pGRKd"></a>## 如何使用实体两种方法<a name="QHA9a"></a>### [EntityManager](https://typeorm.biunav.com/zh/#%E4%BD%BF%E7%94%A8-entity-manager)/scr/index.ts```jsonimport "reflect-metadata";import { createConnection } from "typeorm";import { Post } from "./entity/Post";createConnection().then(async connection => {const posts = await connection.manager.find(Post)console.log(posts)const p = new Post()p.title = 'Post 1'p.content = '我的第一篇文章'await connection.manager.save(p)const posts2 = await connection.manager.find(Post)console.log(posts2)connection.close()}).catch(error => console.log(error));
EntityManagerApi
- await manager.find(User,{name:”gouson”});
- await manager.create(User,{name:”gouson”});
- await manager.save(user1);
- await manager.save([user1,user2,user3]);
- await manager.remove(user1);
- await manager.update(User,1,{name:”gouson”});
- await manager.delete(User,1);
- await manager.findOne(User,1);
封装思路
把所有的操作都放在manager上
把User类、user1对象和其他参数传给managerRepository
Repository Api
cont userRepository =getRepository(User);
await userRepository.findOne(1);
await userRepository.save(user);封装思路
先通过User构造一个repo对象
这个对象就只操作User表
使用seed填充数据
- 也叫数据填充
- 有了数据库,数据表post,但是没数据
- 可以通过seed脚本来构造数据
- 一般不在生产环境运行seed脚本
- 好处
- 别人可以快速运行项目
/src/entity/Post.ts
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';@Entity('posts')export class Post {@PrimaryGeneratedColumn('increment')id: number;@Column('varchar')title: string;@Column('text')content: stringconstructor(title: string, content: string) {this.title = title;this.content = content;}}
/src/seed.tsx
import "reflect-metadata";import { createConnection } from "typeorm";import { Post } from "./entity/Post";createConnection().then(async connection => {const posts = await connection.manager.find(Post)if (posts.length === 0) {let dataArray = []for (let i = 0; i < 10; i++) {dataArray.push(new Post(`Post ${i}`, `第${i}篇文章`))}await connection.manager.save(dataArray)}console.log('posts 数据填充了')connection.close()}).catch(error => console.log(error));
$ yarn dev$ yarn migaration:revert$ yarn migaration:run$ node dist/seed.js


