前言
必须全局安装typeorm命令
typescript
npm i typeorm -g
使用typeorm初始化项目
通过这种方式默认会安装typeorm和ts相关的内容,以及实体类和控制器以及热更新操作
typescript
typeorm init --name MyProject --database mysql --express --module esm
这里面的database还可以用其他数据库
安装依赖
typescript
pnpm i
安装其他依赖
这个时候还需要安装其他依赖项
typescript
pnpm add routing-controllers
pnpm add @types/express @types/body-parser -D
修改模板
删除原有文件的Controller和entity文件,删除route.ts文件
修改tsconfig.json
plain
{
"compilerOptions": {
"lib": [
"es2021"
],
"target": "es2021",
"module": "es2022",
"esModuleInterop": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"outDir": "./build",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true
}
}
配置数据库
在data-source.ts
文件中
typescript
import "reflect-metadata"
import { DataSource } from "typeorm"
export const dataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "123456",
database: "cjh_test",
synchronize: true,
logging: false,
entities: [
"entity/*.ts"
],
subscribers: [
"subscriber/*.ts"
],
migrations: [
"migration/*.ts"
]
})
新增实体类(数据库映射)
在entity目录下新建Article.ts文件
typescript
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity('article')
export class Article{
@PrimaryGeneratedColumn()
id!: number
//指定在数据库的实际名称
@Column({name:'job_no'})
jobNo!: string
@Column()
title!: string
//指定在数据库中的类型
@Column('text')
content!: string
@Column({ name: 'created_by' })
createdBy!: string
@Column({ type: 'date', name: 'created_at' })
createdAt!: string
@Column({ name: 'updated_by' })
updatedBy!: string
@Column({ type: 'date', name: 'updated_at' })
updatedAt!: string
}
这里我创建了一个Article实体类
推荐使用命令来创建一个空的实体类
typescript
typeorm entity:create src/entity/Article
新增服务层(操作数据库)
我们在src下创建一个service目录,并新建article.service.ts
文件
typescript
/**
* 文章服务类
*/
import {dataSource} from '../data-source'
import { Article } from '../entity/Article'
export class ArticleService {
articleRepository
constructor() {
this.articleRepository = dataSource.getRepository(Article)
}
// 查询全部文章
async queryAllArticle() {
return await this.articleRepository.findAndCount()
}
}
新增控制层(业务层)
我们在src下的controller目录中,新建article.controller.ts
文件
typescript
/**
* 文章 controller
*/
import { Controller, Get } from "routing-controllers";
import { ArticleService } from "../services/article.service.js";
//公共前缀
@Controller("/article")
export class ArticleController {
articleService;
constructor() {
this.articleService = new ArticleService();
}
//实际请求 /article/queryArticleList
@Get("/queryArticleList")
queryArticleList() {
return this.articleService.queryAllArticle();
}
}
修改入口文件
修改index.ts
typescript
import express from "express";
import bodyParser from "body-parser";
import { AppDataSource } from "./data-source.js";
import { ArticleController } from "./controller/article.controller.js";
import { BaseController } from "./controller/base.controller.js";
import { useExpressServer } from "routing-controllers";
const { json, urlencoded } = bodyParser;
function init() {
AppDataSource.initialize()
.then(async () => {
console.log("Data Source has been initialized!");
})
.catch((error) => console.log(error));
const app = express();
// body 解析相关中间件
// 解析 json 格式
app.use(json());
// 解析 urlencoded body
// 会在 request 对象上挂载 body 属性,包含解析后的数据。
// 这个新的 body 对象包含 key-value 键值对,若设置 extended 为 true,则键值可以是任意累心个,否则只能是字符串或数组。
app.use(urlencoded({ extended: true }));
// 将当前实例注册到 routing-controllers
useExpressServer(app, {
controllers: [BaseController, ArticleController],
});
app.listen(3000, () => {
console.log(` App is running at http://localhost:3000\n`);
console.log(" Press CTRL-C to stop\n");
});
}
init();
补充一个初始控制器
typescript
import { Controller, Get } from "routing-controllers";
@Controller('/')
export class BaseController {
constructor() {}
@Get('/')
async index() {
return 'hello world'
}
}
运行
typescript
npm start
这个时候你会看到hello world
生成空白迁移文件模版并运行
这一步可以自动帮我们建表
创建迁移文件
typescript
typeorm migration:create src/migration/ArticleTable
typescript
import { MigrationInterface, QueryRunner } from "typeorm";
export class ArticleTable1748858082419 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
}
public async down(queryRunner: QueryRunner): Promise<void> {
}
}
这样就会生成一份迁移文件,up就是更新数据,down就是删除数据
执行迁移文件
typescript
npx typeorm-ts-node-esm migration:run -d ./src/data-source.ts
回滚
typescript
typeorm migration:revert
使用验证模块
vue
npm install class-validator --save
实体类生成迁移文件
这里我们根据实体类生成了迁移文件
plain
"scripts": {
"start": "node --loader ts-node/esm src/index.ts",
"typeorm": "typeorm-ts-node-esm",
"send": "node --loader ts-node/esm public/send.ts",
"receive": "node --loader ts-node/esm public/receive.ts"
}
typescript
npm run typeorm -- migration:generate src/migration/SysLogsDefault -d ./src/data-source.ts
注意要点
必须显式的明确文件后缀
注意tsconfig.json文件 "esModuleInterop": true
执行迁移文件的时候,会记录一次迁移id,如果成功了,下一次就不会再执行迁移了