NestJS 实战(四):一套代码同时连接达梦数据库与MySQL(国产化项目必备)

发布时间:2026/5/28 3:00:50

NestJS 实战(四):一套代码同时连接达梦数据库与MySQL(国产化项目必备) 今天这篇保姆级教程手把手教你用NestJS TypeORM 自定义数据源实现一套代码无缝切换达梦数据库和MySQL全程实战代码从环境搭建到CRUD完整示例让你在国产化项目中既能享受达梦的合规性又能保留MySQL的开发便利性。数据库连接模块可以打包直接复用。如果你觉得有用请关注、点赞、收藏、评论支持一下文末还有粉丝福利1. 先搞懂核心原理NestJS 本身不实现 ORM而是通过模块化集成 TypeORM。但官方nestjs/typeorm模块对达梦这种非原生数据库支持不够友好容易遇到oracledb驱动冲突、方言包补丁失效等问题。我们的解决方案放弃nestjs/typeorm改用自定义提供者手动创建数据源。通过环境变量DB_TYPE动态选择创建MySQL 数据源DataSource或达梦数据源DmdbDataSource。将创建好的数据源实例通过DATA_SOURCE令牌注入到各个服务中。优势✅ 彻底避免驱动冲突连接更稳定✅ 一套 Service 代码无需修改即可操作两种数据库✅ 完全掌控数据库连接生命周期2. 环境准备与依赖安装Node.js 版本要求推荐 Node.js 16.x 或 18.x LTS达梦驱动对高版本支持不完善可用nvm或nvm-windows管理版本创建项目并安装依赖bash# 创建 NestJS 项目 nest new nest-dm-mysql-demo cd nest-dm-mysql-demo # 安装必要依赖注意不安装 nestjs/typeorm npm install nestjs/config typeorm mysql2 dmdb typeorm-dm reflect-metadata依赖说明nestjs/config读取环境变量typeormTypeORM 核心被typeorm-dm依赖mysql2MySQL 驱动dmdb达梦官方 Node.js 驱动typeorm-dm达梦方言包提供DmdbDataSource3. 配置环境变量核心在项目根目录创建.env文件通过DB_TYPE控制使用哪种数据库env# 数据库类型mysql 或 dm DB_TYPEmysql # 通用数据库连接信息 DB_HOSTlocalhost DB_USERNAMEroot DB_PASSWORD123456 # MySQL 专用配置 MYSQL_PORT3306 MYSQL_DBtest_db # 达梦专用配置 DM_PORT5236 DM_SCHEMATEST # 达梦模式名通常与用户名相同切换数据库只需修改DB_TYPE这一个变量4. 数据库模块动态创建数据源关键代码创建src/database/database.module.ts这是整个方案的核心import { Module, Global, Logger } from nestjs/common; import { ConfigModule, ConfigService } from nestjs/config; import { DataSource } from typeorm; import { DmdbDataSource } from typeorm-dm; import { User } from ../user/user.entity; Global() Module({ imports: [ConfigModule], providers: [ { provide: DATA_SOURCE, useFactory: async (configService: ConfigService) { const logger new Logger(DatabaseModule); const dbType configService.getstring(DB_TYPE); let dataSource: DataSource; if (dbType mysql) { // MySQL 数据源 dataSource new DataSource({ type: mysql, host: configService.getstring(DB_HOST), port: configService.getnumber(MYSQL_PORT), username: configService.getstring(DB_USERNAME), password: configService.getstring(DB_PASSWORD), database: configService.getstring(MYSQL_DB), entities: [User], synchronize: true, // 开发环境使用生产请关闭 logging: false, }); } else if (dbType dm) { // 达梦数据源 dataSource new DmdbDataSource({ type: oracle, innerType: dmdb, host: configService.getstring(DB_HOST), port: configService.getnumber(DM_PORT), username: configService.getstring(DB_USERNAME), password: configService.getstring(DB_PASSWORD), schema: configService.getstring(DM_SCHEMA), entities: [User], synchronize: true, logging: false, extra: { connectTimeout: 30000, loginEncrypt: false, // 避免达梦加密错误 }, }); } else { throw new Error(不支持的数据库类型: ${dbType}); } await dataSource.initialize(); logger.log(${dbType} 数据库连接成功); return dataSource; }, inject: [ConfigService], }, ], exports: [DATA_SOURCE], }) export class DatabaseModule {}要点说明type: oracle和innerType: dmdb是达梦方言包的固定写法。loginEncrypt: false用于解决达梦加密错误[6071]。entities数组注册了所有实体可随时添加。5. 定义用户实体创建src/user/user.entity.tsimport { Entity, Column, PrimaryGeneratedColumn } from typeorm; Entity(t_user) export class User { PrimaryGeneratedColumn() id: number; Column({ length: 50 }) name: string; Column({ type: int, nullable: true }) age: number; }注意实体定义完全兼容两种数据库无需任何修改。6. 用户模块与服务用户模块src/user/user.module.tstypescriptimport { Module } from nestjs/common; import { UserService } from ./user.service; import { UserController } from ./user.controller; Module({ providers: [UserService], controllers: [UserController], }) export class UserModule {}用户服务src/user/user.service.tstypescriptimport { Injectable, Inject, NotFoundException } from nestjs/common; import { DataSource, Repository } from typeorm; import { User } from ./user.entity; Injectable() export class UserService { private userRepository: RepositoryUser; constructor(Inject(DATA_SOURCE) private dataSource: DataSource) { this.userRepository this.dataSource.getRepository(User); } async create(userData: PartialUser): PromiseUser { const user this.userRepository.create(userData); return this.userRepository.save(user); } async findAll(): PromiseUser[] { return this.userRepository.find(); } async findOne(id: number): PromiseUser | null { return this.userRepository.findOneBy({ id }); } async update(id: number, updateData: PartialUser): PromiseUser { const user await this.findOne(id); if (!user) { throw new NotFoundException(用户 ID ${id} 不存在); } Object.assign(user, updateData); return this.userRepository.save(user); } async remove(id: number): Promisevoid { const result await this.userRepository.delete(id); if (result.affected 0) { throw new NotFoundException(用户 ID ${id} 不存在); } } }关键点服务中注入的是DataSource类型无论底层是 MySQL 还是达梦都能正确获取Repository。用户控制器src/user/user.controller.tstypescriptimport { Controller, Get, Post, Body, Param, Put, Delete } from nestjs/common; import { UserService } from ./user.service; import { User } from ./user.entity; Controller(users) export class UserController { constructor(private readonly userService: UserService) {} Post() create(Body() userData: PartialUser): PromiseUser { return this.userService.create(userData); } Get() findAll(): PromiseUser[] { return this.userService.findAll(); } Get(:id) findOne(Param(id) id: string): PromiseUser | null { return this.userService.findOne(id); } Put(:id) update(Param(id) id: string, Body() updateData: PartialUser): PromiseUser { return this.userService.update(id, updateData); } Delete(:id) remove(Param(id) id: string): Promisevoid { return this.userService.remove(id); } }7. 根模块整合修改src/app.module.ts导入数据库模块和用户模块typescriptimport { Module } from nestjs/common; import { ConfigModule } from nestjs/config; import { DatabaseModule } from ./database/database.module; import { UserModule } from ./user/user.module; Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, envFilePath: .env, }), DatabaseModule, UserModule, ], }) export class AppModule {}8. 运行测试启动应用bashnpm run start:dev看到如下日志表示连接成功text[Nest] ... LOG [DatabaseModule] mysql 数据库连接成功 或 [Nest] ... LOG [DatabaseModule] dm 数据库连接成功测试 CRUD 接口方法路径功能请求体示例POST/users创建用户{name: 张三, age: 30}GET/users获取所有用户-GET/users/:id获取单个用户-PUT/users/:id更新用户{age: 35}DELETE/users/:id删除用户-使用 Postman 或 curl 测试bash# 创建用户 curl -X POST http://localhost:3000/users -H Content-Type: application/json -d {name:李四,age:25} # 查询所有用户 curl http://localhost:3000/users9. 常见问题与解决方案❌ 问题1达梦连接时报[6071] 消息加密失败解决在达梦配置的extra中添加loginEncrypt: false。❌ 问题2启动后仍提示Oracle package not found原因typeorm-dm的补丁未生效或错误地安装了nestjs/typeorm。解决确保卸载nestjs/typeorm并删除node_modules重新安装。❌ 问题3MySQL 连接时区问题解决在 MySQL 配置中添加timezone: Z或timezone: 08:00。❌ 问题4Node.js 版本过高导致编译失败解决降级到 Node.js 16 或 18 LTS。如果你觉得有用请点赞、收藏、评论支持一下文末还有粉丝福利粉丝提供完整源码

相关新闻