NestJS 集成 MySQL(TypeORM)完整配置与使用指南
一、核心依赖说明
| 依赖名称 | 版本参考 | 功能描述 |
|---|---|---|
@nestjs/typeorm |
^11.0.0 | NestJS 与 TypeORM 的官方集成包,提供模块化支持 |
mysql2 |
^3.14.0 | MySQL 数据库驱动,用于建立数据库连接 |
typeorm |
^0.3.22 | TypeORM 核心库,提供 ORM 数据操作能力 |
依赖安装命令
bash
# 生产环境依赖
npm install @nestjs/typeorm mysql2 typeorm
# 若需类型提示(可选,TypeScript 项目推荐)
npm install @types/mysql --save-dev
二、全局 MySQL 模块配置
2.1 配置文件(src/db/mysql/mysql.module.ts)
采用 @Global() 装饰器实现全局模块,无需在各业务模块中重复导入,统一管理数据库连接配置。
typescript
import { Global, Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
// 导入实体类(可根据项目实际情况调整)
import { User } from '../../entities/user/user.entity';
import { UserLogin } from '../../entities/user/user-login.entity';
import { UserBase } from '../../entities/user/user-base.entity';
@Global() // 标记为全局模块,所有业务模块可直接使用,无需重复导入
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql', // 数据库类型(固定为 mysql,对应 mysql2 驱动)
host: 'localhost', // 数据库主机地址(生产环境替换为实际服务器地址)
port: 3306, // MySQL 默认端口
username: 'root', // 数据库用户名
password: 'your_mysql_password', // 数据库密码(建议通过环境变量配置,避免硬编码)
database: 'sl-sys', // 要连接的数据库名(需提前手动创建)
timezone: 'Z', // 时区配置(Z 表示 UTC 时区,也可配置为 '+08:00' 对应东八区)
entities: [User, UserLogin, UserBase], // 显式注册实体类
autoLoadEntities: true, // 自动加载项目中所有实体类(无需手动全部注册,简化配置)
synchronize: true, // 开发环境:自动同步实体类与数据库表结构(新增/修改字段自动同步)
// logging: true, // 可选:开启 SQL 日志打印,便于开发调试
// charset: 'utf8mb4', // 可选:支持 emoji 等特殊字符,推荐配置
}),
],
// 无需导出,全局模块的配置会自动生效
})
export class MysqlModule {}
2.2 关键配置项说明
| 配置项 | 取值/说明 |
|---|---|
type |
固定为 mysql,指定数据库类型 |
entities |
显式声明需要加载的实体类,与 autoLoadEntities: true 配合使用,双重保障 |
autoLoadEntities |
开启后自动扫描项目中的实体类,无需手动逐个添加,简化维护 |
synchronize |
开发环境设为 true(自动同步表结构),生产环境必须设为 false(避免数据丢失) |
timezone |
时区配置,推荐使用 '+08:00'(东八区),避免时间存储偏差 |
三、实体类设计(数据库表映射)
3.1 核心实体示例(src/entities/user/user.entity.ts)
使用 TypeORM 装饰器实现实体类与 MySQL 表的映射,支持字段属性、关联关系配置。
typescript
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm';
import { UserBase } from './user-base.entity';
// 映射到 MySQL 中的 `user` 表
@Entity('user')
export class User {
// 自增主键(对应 MySQL 的 INT AUTO_INCREMENT)
@PrimaryGeneratedColumn({ comment: '用户自增主键' })
user_id: string; // 字段类型可根据实际需求改为 number
// 普通字段:姓名(varchar 类型,长度 50,非空,带注释)
@Column({ type: 'varchar', name: 'name', comment: '用户姓名', length: 50, nullable: false })
name: string;
// 密码字段:查询时默认不返回(select: false),避免密码泄露
@Column({ type: 'varchar', name: 'password', comment: '用户密码(加密存储)', length: 100, select: false })
password: string;
// 一对一关联:User 关联 UserBase(通过 user_id 外键)
@OneToOne(() => UserBase) // 关联的目标实体类
@JoinColumn({ name: 'user_id', referencedColumnName: 'user_id' }) // 外键配置(当前表 user_id 关联 UserBase 的 user_id)
user_base: UserBase; // 关联的实体对象
}
3.2 装饰器核心说明
| 装饰器 | 功能描述 |
|---|---|
@Entity('tableName') |
标记为实体类,指定映射的 MySQL 表名 |
@PrimaryGeneratedColumn |
定义自增主键,默认对应 MySQL 的 INT AUTO_INCREMENT |
@Column |
定义普通数据库字段,支持 type、name、length、nullable 等属性配置 |
@OneToOne |
定义一对一关联关系,需配合 @JoinColumn 指定外键 |
@JoinColumn |
配置外键关联,name 为当前表的外键字段,referencedColumnName 为目标表的关联字段 |
select: false |
查询该实体时,默认不返回该字段(如密码字段),提升安全性 |
四、根模块注册(app.module.ts)
在项目根模块中导入全局 MySQL 模块,使其在整个项目中生效。
typescript
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MysqlModule } from './db/mysql/mysql.module'; // 导入全局 MySQL 模块
import { UserModule } from './service/user/user.module';
import { AuthModule } from './service/auth/auth.module';
@Module({
imports: [
// 环境变量配置(全局生效)
ConfigModule.forRoot({ isGlobal: true }),
MysqlModule, // 导入 MySQL 全局模块,所有业务模块可直接使用数据库操作
UserModule, // 业务模块
AuthModule, // 认证模块
// 其他业务模块...
],
controllers: [],
providers: [],
})
export class AppModule {}
五、数据库操作(服务层实现)
5.1 核心服务示例(src/service/user/user.service.ts)
通过 @InjectRepository 注入 TypeORM Repository 对象,实现数据库的查询、新增、修改、删除等操作。
typescript
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '../../entities/user/user.entity';
@Injectable()
export class UserService {
// 注入 User 实体的 Repository(数据访问对象)
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>,
) {}
/**
* 根据用户ID查询用户信息(连表查询 User 与 UserBase)
* @param user_id 用户ID
* @returns 用户完整信息(包含 user_base 关联数据)
*/
async getUserInfo(user_id: string) {
return await this.userRepository
.createQueryBuilder('user') // 别名:user
.leftJoinAndSelect('user.user_base', 'user_base') // 左连接 UserBase,别名:user_base
.where('user.user_id = :id', { id: user_id }) // 查询条件
.getOne(); // 获取单条数据(若无数据返回 null)
}
/**
* 新增用户
* @param userData 用户信息
* @returns 新增后的用户数据
*/
async createUser(userData: Partial<User>) {
const user = this.userRepository.create(userData); // 创建实体实例
return await this.userRepository.save(user); // 保存到数据库
}
/**
* 修改用户信息
* @param user_id 用户ID
* @param updateData 要修改的字段
* @returns 修改结果
*/
async updateUser(user_id: string, updateData: Partial<User>) {
return await this.userRepository
.createQueryBuilder()
.update(User)
.set(updateData)
.where('user_id = :id', { id: user_id })
.execute();
}
/**
* 删除用户
* @param user_id 用户ID
* @returns 删除结果
*/
async deleteUser(user_id: string) {
return await this.userRepository
.createQueryBuilder()
.delete()
.from(User)
.where('user_id = :id', { id: user_id })
.execute();
}
}
5.2 核心操作说明
- Repository 注入 :通过
@InjectRepository(实体类)注入对应的数据访问对象,提供基础 CRUD 操作 - 查询构建器 :
createQueryBuilder提供灵活的 SQL 构建能力,支持连表、条件查询、分页等复杂操作 - 基础操作 :
create:创建实体实例(不直接入库)save:保存实体(新增/修改,根据主键是否存在自动判断)update/delete:批量更新/删除,通过execute()执行操作
六、项目目录结构
采用分层设计,职责清晰,便于维护和扩展。
src/
├── db/ # 数据库配置目录
│ └── mysql/
│ └── mysql.module.ts # MySQL 全局配置模块
├── entities/ # 实体类目录(对应数据库表)
│ └── user/ # 用户相关实体
│ ├── user.entity.ts # User 实体(映射 user 表)
│ ├── user-base.entity.ts # UserBase 实体(映射 user_base 表)
│ └── user-login.entity.ts # UserLogin 实体(映射 user_login 表)
├── service/ # 业务服务目录
│ └── user/ # 用户业务模块
│ ├── user.service.ts # 用户业务逻辑 + 数据库操作
│ ├── user.controller.ts # 用户接口控制器
│ └── user.module.ts # 用户模块配置
│ └── auth/ # 认证业务模块
├── app.module.ts # 项目根模块(注册全局模块 + 业务模块)
└── main.ts # 项目入口文件
七、核心特点总结
- 全局模块化 :
MysqlModule标记为全局模块,所有业务模块无需重复导入,简化配置 - TypeORM 强集成 :通过
TypeOrmModule快速实现数据库连接,支持实体映射、查询构建器等强大功能 - 安全可靠 :密码字段默认不返回(
select: false),开发/生产环境配置隔离(synchronize开关) - 易于维护:实体类与数据库表一一映射,目录结构清晰,业务逻辑与数据操作分离
- 功能灵活:支持一对一关联查询、动态 SQL 构建,满足复杂业务场景需求
八、生产环境优化建议
-
环境变量配置 :将数据库主机、用户名、密码等配置通过
.env文件管理,避免硬编码typescript// 优化后的 mysql.module.ts 配置(读取环境变量) TypeOrmModule.forRootAsync({ inject: [ConfigService], useFactory: (configService: ConfigService) => ({ type: 'mysql', host: configService.get('DB_HOST'), port: configService.get('DB_PORT'), username: configService.get('DB_USERNAME'), password: configService.get('DB_PASSWORD'), database: configService.get('DB_DATABASE'), entities: [User, UserLogin, UserBase], autoLoadEntities: true, synchronize: false, // 生产环境禁用自动同步 logging: false, // 生产环境关闭 SQL 日志 charset: 'utf8mb4', }), }) -
关闭
synchronize:生产环境必须设为false,通过 TypeORM 迁移工具(typeorm migration:run)管理表结构变更 -
连接池配置 :添加连接池配置,提升数据库连接复用率和性能
typescriptTypeOrmModule.forRoot({ // 其他配置... extra: { connectionLimit: 10, // 连接池最大连接数 }, }) -
实体索引 :为常用查询字段添加索引,提升查询性能
typescript@Column({ type: 'varchar', name: 'name', comment: '用户姓名', length: 50, nullable: false, unique: true }) // 或手动添加索引 @Index('idx_user_name', ['name'])