第七部分:第四节 - 在 NestJS 应用中集成 MySQL (使用 TypeORM):结构化厨房的原材料管理系统
在 NestJS 这样一个结构化的框架中,我们更倾向于使用 ORM (Object-Relational Mapper) 来与关系型数据库交互。ORM 就像中央厨房里一套智能化的原材料管理系统,它将数据库中的表格和行映射到我们熟悉的对象和类的实例。我们可以使用面向对象的方式来操作数据,ORM 会负责将其转换为底层的 SQL 语句。这大大提高了开发效率和代码的可读性,并且 TypeORM 对 TypeScript 有很好的支持。
ORM 的优势:
- 面向对象的操作: 使用对象而不是 SQL 语句来操作数据库。
- 提高开发效率: 减少手写重复的 SQL 代码。
- 更好的类型安全: 结合 TypeScript,可以在编译时检查数据结构的匹配。
- 数据库无关性(一定程度): 更换数据库类型(如从 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.forRoot
和 TypeOrmModule.forFeature
在 NestJS 中配置和注册 TypeORM。在 Service 中注入 Repository 并使用其方法进行数据访问是 NestJS + TypeORM 的标准模式,这使得数据层逻辑清晰、类型安全且易于测试。
练习:
- 确保你的 NestJS 项目已安装 TypeORM 和
mysql2
。 - 修改
app.module.ts
,配置 TypeORM 连接你的 MySQL 数据库my_bookstore_db
,并指定实体文件路径。 - 为你的“书籍”或“任务”资源,在相应的模块中创建一个实体文件 (
book.entity.ts
或task.entity.ts
),使用 TypeORM 装饰器映射到数据库表。 - 修改相应的模块文件 (
books.module.ts
或tasks.module.ts
),使用TypeOrmModule.forFeature()
注册你的实体。 - 修改相应的 Service 文件 (
books.service.ts
或tasks.service.ts
),注入实体对应的 Repository。 - 使用 Repository 的方法(
find
,findOne
,create
,save
,delete
)替换之前使用内存数组实现的 CRUD 逻辑。确保方法返回 Promise,并在 Service 中处理找不到数据的情况(抛出NotFoundException
)。 - 修改相应的 Controller 文件,确保在调用 Service 方法时使用了
await
。 - 运行应用,并使用 Postman 等工具测试你的 API,验证数据是否正确地存储和读取自 MySQL 数据库。
相关文章:
第七部分:第四节 - 在 NestJS 应用中集成 MySQL (使用 TypeORM):结构化厨房的原材料管理系统
在 NestJS 这样一个结构化的框架中,我们更倾向于使用 ORM (Object-Relational Mapper) 来与关系型数据库交互。ORM 就像中央厨房里一套智能化的原材料管理系统,它将数据库中的表格和行映射到我们熟悉的对象和类的实例。我们可以使用面向对象的方式来操作…...
Bug 背后的隐藏剧情
Bug 背后的隐藏剧情 flyfish 1. 「bug」:70多年前那只被拍进史书的飞蛾 故事原型:1947年哈佛实验室的「昆虫命案」 1947年的计算机长啥样?像一间教室那么大,塞满了几万根继电器(类似老式开关)ÿ…...
Golang | 搜索哨兵-对接分布式gRPC服务
哨兵(centennial)负责接待客人,直接与调用方对接。哨兵的核心组件包括service HUB和connection pool。service HUB用于与服务中心通信,获取可提供服务的节点信息。connection pool用于缓存与index worker的连接,避免每…...

智慧充电桩数字化管理平台:环境监测与动态数据可视化技术有哪些作用?
随着新能源汽车的普及,智慧充电桩作为基础设施的重要组成部分,正逐步向数字化、智能化方向发展。环境监测与动态数据可视化技术的应用,为充电桩的高效管理和运维提供了全新解决方案。通过实时采集环境参数与运行数据,并结合可视化…...
debian12.9或ubuntu,vagrant离线安装插件vagrant-libvirt
系统盘: https://mirror.lzu.edu.cn/debian-cd/12.9.0/amd64/iso-dvd/debian-12.9.0-amd64-DVD-1.iso 需要的依赖包,无需安装ruby( sudo apt install -y ruby-full ruby-dev rubygems ) : apt install -y iptables; apt install -y curl;rootdebian129:~# dpkg -l iptables …...

家政小程序开发,开启便捷生活新篇章
在快节奏的现代生活中,家务琐事常常让人分身乏术,如何高效解决家政服务需求成了众多家庭的难题。家政小程序开发,正是为解决这一痛点而生,它将为您带来前所未有的便捷生活体验。 想象一下,您只需打开手机上的家政小程…...
C++ 重载(Overload)、重写(Override)、隐藏(Hiding) 的区别
C 重载(Overload)、重写(Override)、隐藏(Hiding) 的区别 这三个概念是 C 面向对象的核心知识点,也是面试必问内容。下面我们从定义、发生条件、代码示例、底层原理全方位解析它们的区别。 一、核心区别对比表(速记版) 特性重载(Overload)…...

李臻20242817_安全文件传输系统项目报告_第14周
安全文件传输系统项目报告(第 14 周) 1. 代码链接 Gitee 仓库地址:https://gitee.com/li-zhen1215/homework/tree/master/Secure-file 代码结构说明: SecureFileTransfer/ ├── client/ # 客户端主目…...

20250531MATLAB三维绘图
MATLAB三维绘图 三维曲线:plot3功能介绍代码实现过程plot3实现效果 三维曲面空间曲面作图命令:meshmeshgrid语法示例应用meshgrid实操训练 peakspeaks 的基本用法peaks数学表达式实操训练自定义网格大小使用自定义网格 meshMATLAB代码对齐快捷键Ctrli墨西…...

深入理解C#异步编程:原理、实践与最佳方案
在现代软件开发中,应用程序的性能和响应能力至关重要。特别是在处理I/O密集型操作(如网络请求、文件读写、数据库查询)时,传统的同步编程方式会导致线程阻塞,降低程序的吞吐量。C# 的异步编程模型(async/aw…...

基于千帆大模型的AI体检报告解读系统实战:使用OSS与PDFBox实现PDF内容识别
目录 说明 前言 需求 流程说明 表结构说明 整体流程 百度智能云 注册和实名认证 创建应用 费用说明 大模型API说明 集成大模型 设计Prompt 上传体检报告 读取PDF内容 功能实现 智能评测 抽取大模型工具 功能实现 总结 说明 AI体检报告解读、病例小结或者…...
Redis缓存落地总结
最近在优化电子签系统,涉及到缓存相关的也一并优化了,写个文档做个总结,防止以后开发时又考虑不全 1、避免大key 避免缓存大PDF文件: 💡 经验值:单个Redis Value不超过10KB,集合元素不超过500…...

Spring,SpringMVC,SpringBoot
1.Spring最核心包括aop和ioc概念 AOP 能够将将哪些于业务无关的,并且大量重复的业务逻辑进行封装起来,便于减少重复代码,降低模块之间的耦合度,给未来的系统更好的可用性和可维护性。 Spring中AOP是采用动态代理,JDK代…...
npm、pnpm、yarn使用以及区别
npm 使用 安装包:在项目目录下,npm install <包名> 用于本地安装包到 node_modules 目录,并添加到 package.json 的 dependencies 中;npm install -g <包名> 用于全局安装,适用于命令行工具等。初始化项目…...
flutter加载dll 报错问题
解决flutter加载dll 报错问题 LoadLibrary 报错 126 or 193 明确一点:flutter构建exe 时默认是MSVC的。 1. 先检查dll 的位数是否满足 file ***.dll output: PE32 executable (DLL) (console) x86-64, for MS Windows, 19 sections 这种是64位的机器。 满足的话可…...

数据分析学习笔记——A/B测试
目录 前言 A/B测试中的统计学方法 假设检验 Levenes Test莱文测试 t 检验(两组均值差异) 实战案例 数据来源及参考资料 代码详解 导入数据 计算ROI Request检验 GMV检验 ROI检验 结语 前言 什么是A/B测试?说白了就是中学生物实…...
【python深度学习】Day 41 简单CNN
知识回顾 数据增强卷积神经网络定义的写法batch归一化:调整一个批次的分布,常用与图像数据特征图:只有卷积操作输出的才叫特征图调度器:直接修改基础学习率 卷积操作常见流程如下: 1. 输入 → 卷积层 → Batch归一化层…...

基于RK3568/RK3588/全志H3/飞腾芯片/音视频通话程序/语音对讲/视频对讲/实时性好/极低延迟
一、前言说明 近期收到几个需求都是做音视频通话,很多人会选择用webrtc的方案,这个当然是个不错的方案,但是依赖的东西太多,而且相关组件代码量很大,开发难度大。所以最终选择自己属性的方案,那就是推流拉…...

解决 Win11 睡眠后黑屏无法唤醒的问题
目录 一、问题描述二、解决方法1. 禁用快速启动2. 设置 Management Engine Interface3. 允许混合睡眠其他命令 4. 修复系统文件5. 更新 Windows 或驱动程序6. 其他1)更改电源选项2)刷新 Hiberfil.sys 文件3)重置电源计划4)运行系统…...

[ElasticSearch] RestAPI
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...

Linux中的shell脚本
什么是shell脚本 shell脚本是文本的一种shell脚本是可以运行的文本shell脚本的内容是由逻辑和数据组成shell脚本是解释型语言 用file命令可以查看文件是否是一个脚本文件 file filename 脚本书写规范 注释 单行注释 使用#号来进行单行注释 多行注释 使用 : " 注释内容…...

dvwa3——CSRF
LOW: 先尝试change一组密码:123456 修改成功,我们观察上面的url代码 http://localhost/DVWA/vulnerabilities/csrf/?password_new123456&password_conf123456&ChangeChange# 将password_new部分与password_conf部分改成我们想要的…...

【学习笔记】Transformer
学习的博客(在此致谢): 初识CV - Transformer模型详解(图解最完整版) 1 整体结构 Transformer由Encoder和Decoder组成,分别包含6个block。 Transformer的工作流程大体如下: 获取每个单词的em…...

欢乐熊大话蓝牙知识12:用 BLE 打造家庭 IoT 网络的三种方式
🏠 用 BLE 打造家庭 IoT 网络的三种方式 不止是“蓝牙耳机”,BLE 还能把你家“点亮成精”! 👋 前言:BLE 不只是蓝牙耳机的“代名词” 蓝牙?很多人一听就联想到“耳机连接失败请重试”。但你知道吗?现在 BLE(Bluetooth Low Energy)在智能家居中已经偷偷搞起了大事情。…...

02.上帝之心算法用GPU计算提速50倍
本文介绍了上帝之心的算法及其Python实现,使用Python语言的性能分析工具测算性能瓶颈,将算法最耗时的部分重构至CUDA C语言在纯GPU上运行,利用GPU核心更多并行更快的优势显著提高算法运算速度,实现了结果不变的情况下将耗时缩短五…...

MES管理系统:Java+Vue,含源码与文档,实现生产过程实时监控、调度与优化,提升制造企业效能
前言: 在当今竞争激烈的制造业环境中,企业面临着提高生产效率、降低成本、提升产品质量以及快速响应市场变化等多重挑战。MES管理系统作为连接企业上层计划管理系统与底层工业控制之间的桥梁,扮演着至关重要的角色。它能够实时收集、分析和处…...

LeetCode算法题 (搜索二维矩阵)Day18!!!C/C++
https://leetcode.cn/problems/search-a-2d-matrix/description/ 一、题目分析 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 ta…...

VectorStore 组件深入学习与检索方法
考虑到目前市面上的向量数据库众多,每个数据库的操作方式也无统一标准,但是仍然存在着一些公共特征,LangChain 基于这些通用的特征封装了 VectorStore 基类,在这个基类下,可以将方法划分成 6 种: 相似性搜…...

HackMyVM-First
信息搜集 主机发现 ┌──(kali㉿kali)-[~] └─$ nmap -sn 192.168.43.0/24 Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-31 06:13 EDT Nmap scan report for 192.168.43.1 Host is up (0.0080s latency). MAC Address: C6:45:66:05:91:88 (Unknown) …...
30V/150A MOSFET 150N03在无人机驱动动力系统中的性能边界与热设计挑战
产品技术概述 150N03 是一款基于沟槽式工艺(Trench Technology)的N沟道功率MOSFET,其核心价值在于: 电压/电流规格:VDSS30V, ID150A (Tc25℃) 工艺特征:高密度元胞设计实现超低导通电阻 双面散热架构:顶部裸露铜架底…...