目标:
把现在的:
private books = []
变成:
Controller
↓
Service
↓
TypeORM
↓
MySQL
真正实现数据持久化。
第一步:准备 MySQL
先确认你的电脑有 MySQL。
查看版本:
mysql --version
例如:
mysql Ver 8.0.xx
如果没有安装,可以安装:
- MySQL 8.x(推荐)
- MariaDB(也可以)
创建数据库
登录:
mysql -u root -p
创建数据库:
CREATE DATABASE nest_book;
查看:
SHOW DATABASES;
应该能看到:
nest_book
第二步:安装 TypeORM
Nest 官方推荐 ORM 是:
TypeORM
安装:
pnpm add @nestjs/typeorm typeorm mysql2
作用:
| 包 | 作用 |
|---|---|
| @nestjs/typeorm | Nest 集成 |
| typeorm | ORM 核心 |
| mysql2 | MySQL 驱动 |
第三步:配置数据库连接
修改:
src/app.module.ts
导入:
import { TypeOrmModule } from '@nestjs/typeorm';
修改:
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: '123456',
database: 'nest_book',
autoLoadEntities: true,
synchronize: true,
}),
BooksModule,
],
})
export class AppModule {}
配置解释
synchronize
synchronize: true
开发环境:
实体变化
↓
自动修改表结构
方便开发。
生产环境必须:
synchronize: false
autoLoadEntities
autoLoadEntities: true
自动加载所有 Entity。
不用手动注册。
第四步:创建 Entity
打开:
src/books/entities/book.entity.ts
修改:
import {
Entity,
Column,
PrimaryGeneratedColumn,
} from 'typeorm';
@Entity()
export class Book {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
author: string;
}
理解
Entity
@Entity()
表示:
Book
↓
映射成数据库表
主键
@PrimaryGeneratedColumn()
id: number;
对应:
id INT AUTO_INCREMENT PRIMARY KEY
字段
@Column()
name: string;
对应:
name VARCHAR(255)
第五步:注册 Entity
修改:
src/books/books.module.ts
导入:
import { TypeOrmModule } from '@nestjs/typeorm';
import { Book } from './entities/book.entity';
修改:
@Module({
imports: [
TypeOrmModule.forFeature([Book]),
],
controllers: [BooksController],
providers: [BooksService],
})
export class BooksModule {}
为什么?
Nest DI 容器需要知道:
Book Repository
从哪里来。
所以:
TypeOrmModule.forFeature([Book])
负责注册 Repository。
第六步:注入 Repository
修改:
books.service.ts
导入:
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Book } from './entities/book.entity';
构造函数:
constructor(
@InjectRepository(Book)
private readonly bookRepository: Repository<Book>,
) {}
现在:
bookRepository
相当于:
SELECT *
INSERT
UPDATE
DELETE
操作器。
第七步:实现查询全部
修改:
findAll() {
return this.bookRepository.find();
}
测试:
GET /books
如果表为空:
[]
第八步:实现新增
修改:
async create(createBookDto: CreateBookDto) {
const book =
this.bookRepository.create(createBookDto);
return await this.bookRepository.save(book);
}
create
只是创建对象:
const book =
this.bookRepository.create(dto);
内存中:
{
name:'NestJS',
author:'Tom'
}
save
真正写数据库:
await this.bookRepository.save(book);
执行:
INSERT INTO book ...
测试:
POST /books
{
"name":"NestJS实战",
"author":"Tom"
}
返回:
{
"id":1,
"name":"NestJS实战",
"author":"Tom"
}
查看数据库:
SELECT * FROM book;
结果:
| id | name | author |
|---|---|---|
| 1 | NestJS实战 | Tom |
第九步:实现查询单个
findOne(id: number) {
return this.bookRepository.findOne({
where: { id },
});
}
测试:
GET /books/1
返回:
{
"id":1,
"name":"NestJS实战",
"author":"Tom"
}
第十步:实现删除
remove(id: number) {
return this.bookRepository.delete(id);
}
测试:
DELETE /books/1
返回:
{
"affected":1
}
第十一步:实现更新
async update(
id: number,
updateBookDto: UpdateBookDto,
) {
await this.bookRepository.update(
id,
updateBookDto,
);
return this.findOne(id);
}
测试:
PATCH /books/1
{
"author":"Jerry"
}
再次查询:
GET /books/1
返回:
{
"id":1,
"name":"NestJS实战",
"author":"Jerry"
}
到这里,你已经掌握了:
✅ Entity
✅ Repository
✅ MySQL连接
✅ TypeORM集成
✅ CRUD持久化
✅ DI注入Repository
现在项目已经从"玩具项目"升级成"真实后端项目"。