启动数据库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
```json
import "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: string
constructor(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