当前位置: 首页 > news >正文

第七部分:第四节 - 在 NestJS 应用中集成 MySQL (使用 TypeORM):结构化厨房的原材料管理系统

在 NestJS 这样一个结构化的框架中,我们更倾向于使用 ORM (Object-Relational Mapper) 来与关系型数据库交互。ORM 就像中央厨房里一套智能化的原材料管理系统,它将数据库中的表格和行映射到我们熟悉的对象和类的实例。我们可以使用面向对象的方式来操作数据,ORM 会负责将其转换为底层的 SQL 语句。这大大提高了开发效率和代码的可读性,并且 TypeORM 对 TypeScript 有很好的支持。

ORM 的优势:

  1. 面向对象的操作: 使用对象而不是 SQL 语句来操作数据库。
  2. 提高开发效率: 减少手写重复的 SQL 代码。
  3. 更好的类型安全: 结合 TypeScript,可以在编译时检查数据结构的匹配。
  4. 数据库无关性(一定程度): 更换数据库类型(如从 MySQL 换到 PostgreSQL)时,改动可能较小。

TypeORM 简介:

TypeORM 是一个功能强大的 ORM,支持多种数据库(MySQL, PostgreSQL, SQLite, MongoDB 等),并且对 TypeScript 和 JavaScriptES6+/ES7+ 有很好的支持,与 NestJS 集成非常方便。

安装 TypeORM 和 MySQL 连接器:

在你的 NestJS 项目目录中:

npm install typeorm mysql2 @nestjs/typeorm @types/node --save
# 或者 yarn add typeorm mysql2 @nestjs/typeorm @types/node
  • typeorm: TypeORM 核心库
  • mysql2: MySQL 数据库驱动
  • @nestjs/typeorm: NestJS 与 TypeORM 集成的模块
  • @types/node: Node.js 类型定义(如果项目还没有)

在 NestJS 中配置 TypeORM 模块:

通常在根模块 (AppModule) 中配置数据库连接。

src/app.module.ts (修改):

// src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; // 导入 TypeOrmModule
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UsersModule } from './users/users.module'; // 假设你已经有了 UsersModule@Module({imports: [TypeOrmModule.forRoot({ // 配置数据库连接type: 'mysql',      // 数据库类型host: 'localhost',port: 3306,username: 'your_mysql_username',password: 'your_mysql_password',database: 'my_webapp_db',entities: [__dirname + '/**/*.entity{.ts,.js}'], // 实体文件路径synchronize: true, // 生产环境中不要使用这个!它会在每次应用启动时同步数据库结构。开发环境方便。}),UsersModule, // 导入你的用户模块// ... 导入其他模块],controllers: [AppController],providers: [AppService],
})
export class AppModule {}

__dirname + '/**/*.entity{.ts,.js}' 告诉 TypeORM 在当前文件所在目录及其子目录下查找所有以 .entity.ts.entity.js 结尾的文件作为实体文件。

定义实体 (Entities):

实体是用于映射数据库表的 TypeScript 类。使用 TypeORM 提供的装饰器来定义表的结构。

创建一个文件 src/users/entities/user.entity.ts

// src/users/entities/user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, Unique } from 'typeorm';@Entity('users') // @Entity() 装饰器指定这个类映射到哪个数据库表 (如果省略,默认为类名的小写)
export class User {@PrimaryGeneratedColumn() // @PrimaryGeneratedColumn() 装饰器指定这是主键,并且是自动递增的id: number;@Column({ length: 50, unique: true }) // @Column() 装饰器指定这是一个普通列,可以配置属性 (长度、唯一性等)username: string;@Column({ unique: true, nullable: true }) // nullable: true 表示该列可以为 NULLemail: string;@Column({ nullable: true })age: number;@CreateDateColumn() // @CreateDateColumn() 装饰器指定这是一个创建时间列,通常自动生成created_at: Date;
}

仓库 (Repositories):

Repository 是 TypeORM 提供的一个模式,用于对特定实体进行数据操作。每个实体都有一个对应的 Repository。Repository 提供了常用的数据操作方法(查找、保存、删除等),以及 Query Builder 等更高级的查询工具。这就像仓库管理员提供了一套标准的工具(Repository)来获取特定类型的原材料(Entity)。

在 Service 中使用 Repository:

在 Service 中,通过依赖注入获取对应实体的 Repository 实例,然后使用 Repository 的方法进行数据操作。

修改 src/users/users.module.ts,注册 User 实体:

// src/users/users.module.ts (修改)
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm'; // 导入 TypeOrmModule
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { User } from './entities/user.entity'; // 导入 User 实体@Module({imports: [TypeOrmModule.forFeature([User]) // TypeOrmModule.forFeature() 用于在功能模块中注册实体],controllers: [UsersController],providers: [UsersService],exports: [UsersService] // 如果其他模块需要 UsersService,需要导出
})
export class UsersModule {}

修改 src/users/users.service.ts,注入 UserRepository 并使用它:

// src/users/users.service.ts (修改)
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; // 导入 InjectRepository
import { Repository } from 'typeorm'; // 导入 Repository
import { User } from './entities/user.entity'; // 导入 User 实体
import { CreateUserDto } from './dto/create-user.dto'; // 导入 DTO
import { UpdateUserDto } from './dto/update-user.dto';@Injectable()
export class UsersService {// 通过 @InjectRepository() 装饰器注入 User 实体对应的 Repositoryconstructor(@InjectRepository(User)private usersRepository: Repository<User>,) {}// 获取所有用户findAll(): Promise<User[]> { // 返回 Promise<User[]>return this.usersRepository.find(); // 使用 Repository 的 find 方法}// 获取单个用户findOne(id: number): Promise<User | undefined> { // 返回 Promise<User | undefined>return this.usersRepository.findOne({ where: { id } }); // 使用 findOne 方法根据 ID 查找}// 创建用户async create(createUserDto: CreateUserDto): Promise<User> {const newUser = this.usersRepository.create(createUserDto); // 创建一个实体对象 (在内存中)return this.usersRepository.save(newUser); // 保存到数据库,返回保存后的实体 (包含生成的 ID)}// 更新用户async update(id: number, updateUserDto: UpdateUserDto): Promise<User> {const userToUpdate = await this.usersRepository.findOne({ where: { id } });if (!userToUpdate) {throw new NotFoundException(`找不到 ID 为 ${id} 的用户`);}// 合并更新数据到实体对象this.usersRepository.merge(userToUpdate, updateUserDto);// 保存更新后的实体到数据库return this.usersRepository.save(userToUpdate);}// 删除用户async remove(id: number): Promise<void> {const deleteResult = await this.usersRepository.delete(id); // 使用 delete 方法if (deleteResult.affected === 0) { // deleteResult.affected 表示受影响的行数throw new NotFoundException(`找不到 ID 为 ${id} 的用户,无法删除`);}}
}

注意 Service 中的方法现在返回的是 Promise,因为数据库操作是异步的。控制器中调用 Service 方法时,需要使用 await

小结: TypeORM 是在 NestJS 中集成 MySQL 的常用 ORM。它通过实体 (Entities) 将数据库表映射为对象,通过仓库 (Repositories) 提供面向对象的数据操作方法。通过 TypeOrmModule.forRootTypeOrmModule.forFeature 在 NestJS 中配置和注册 TypeORM。在 Service 中注入 Repository 并使用其方法进行数据访问是 NestJS + TypeORM 的标准模式,这使得数据层逻辑清晰、类型安全且易于测试。

练习:

  1. 确保你的 NestJS 项目已安装 TypeORM 和 mysql2
  2. 修改 app.module.ts,配置 TypeORM 连接你的 MySQL 数据库 my_bookstore_db,并指定实体文件路径。
  3. 为你的“书籍”或“任务”资源,在相应的模块中创建一个实体文件 (book.entity.tstask.entity.ts),使用 TypeORM 装饰器映射到数据库表。
  4. 修改相应的模块文件 (books.module.tstasks.module.ts),使用 TypeOrmModule.forFeature() 注册你的实体。
  5. 修改相应的 Service 文件 (books.service.tstasks.service.ts),注入实体对应的 Repository。
  6. 使用 Repository 的方法(find, findOne, create, save, delete)替换之前使用内存数组实现的 CRUD 逻辑。确保方法返回 Promise,并在 Service 中处理找不到数据的情况(抛出 NotFoundException)。
  7. 修改相应的 Controller 文件,确保在调用 Service 方法时使用了 await
  8. 运行应用,并使用 Postman 等工具测试你的 API,验证数据是否正确地存储和读取自 MySQL 数据库。

相关文章:

  • 剑指offer hot100 第三周
  • 查看make命令执行后涉及的预编译宏定义的值
  • java synchronized关键字用法
  • io流2——字节输入流,文件拷贝
  • Codeforces 1027 Div3(ABCDEF)
  • Java网络编程基础:从阻塞式I/O到线程池模型
  • DAY 34 超大力王爱学Python
  • C++ —— STL容器——string类
  • ps中通过拷贝的图层和通过剪切的图层
  • java多线程与JUC
  • ck-editor5的研究 (4):初步使用 CKEditor5 的插件功能
  • Cesium快速入门到精通系列教程三
  • 高速串行接口
  • Spring Boot 4.0实战:构建高并发电商系统
  • ArkTS基础
  • spining-lidar的电机和激光雷达体(lidar-imu)之间的标定
  • VMware-VMRC-12.0.1-18113358安装包下载安装与使用(附下载)
  • 数学分析——一致性(均匀性)和收敛
  • 高速串行通信解惑说明
  • ReLU的变体
  • 丽水建设网站/百度seo优化方案
  • 浙江住房和城乡建设部网站/推广普通话手抄报一等奖
  • 做网站资金来源是什么/海口seo快速排名优化
  • 买卖网站建设/百度推广退款电话
  • 烟台做外贸网站/seo收费低
  • 女頻做的最好的网站/西安seo网站排名