Nestjs框架: 多租户与多数据库的架构设计与实现

Nestjs框架: 数据库多租户模式与动态模块初探 本文探讨了如何通过动态模块和依赖注入实现多租户数据库系统的集成。文章首先概述了TypeORM、Prisma和Mongoose三种ORM框架的基本连接方式,重点分析了Prisma在多库场景下的动态配置需求。通过研究Prisma的文档,提出了通过程序化覆盖数据源URL的方案,将连接信息拆分为独立字段管理。随后深入剖析了NestJS动态模块的实现原理,通过分析TypeORM模块源码和官方文档示例,展示了如何通过forRootAsync方法实现配置的动态注入。最后,文章通过一个多租户场景案例,阐述了如何利用动态模块 阅读详情

概述

  • 在 NestJS 项目中实现多数据库对接,尤其是结合 TypeORM、Prisma 和 Mongoose 三种不同类型的 OM(对象关系映射)库,来应对多租户架构下的数据隔离与灵活切换需求
  • 在现代企业级应用开发中,项目的模型层往往需要根据具体的业务场景来选择合适的数据库与对应的 OM 库。
  • 在大多数情况下,不会在同一个项目中同时使用三种数据库,而是根据应用场景来决定是否需要支持多数据库连接
  • 只有在项目中确实需要对接多种数据库时,才需要使用我们所讲的最小可行性方案
  • 这个方案的核心思想是通过分层来统一接口,再根据不同的数据库类型实现具体的操作逻辑
  • 这样,我们就不需要每种数据库都 inject 一次服务,通过统一的服务内部租户身份来进行区分,相当于外观(门面)模式 + 抽象工厂模式 + 策略模式

多租户与多数据库架构下的挑战与优化

  • 在多租户系统中,数据隔离是一个核心问题。传统的单库架构无法满足多租户场景下的数据隔离与性能要求。因此,我们需要考虑多库架构(即每个租户拥有独立数据库)
  • 然而,多库架构也带来了如下挑战
    • 系统复杂度提升: 多库意味着更多的数据库连接、配置管理与数据迁移逻辑
    • 维护成本上升: 数据库数量增加,对运维和监控系统提出了更高要求
    • 数据同步问题: 跨库数据同步、一致性保障、事务处理等都需要额外设计
  • 为解决这些问题,我们在项目中设计了一套基于多 ORM 库的动态数据库连接机制:
    • 数据库连接信息可以从本地配置文件读取
    • 也可以通过远程服务动态获取(如根据不同租户 ID 获取其数据库连接信息)
    • 支持不同类型 OM 库(如 TypeORM、Prisma、Mongoose)的动态切换

ORM 库的适用场景与选型建议

  • 在选择 ORM 库时,我们需要根据数据库类型与业务需求进行合理选择:
    • TypeORM:更适合关系型数据库(如 MySQL、PostgreSQL),对非关系型数据库(如 MongoDB)支持有限
    • Prisma:支持关系型与非关系型数据库,但版本更新频繁,社区支持不如 TypeORM 稳定
    • Mongoose:专为 MongoDB 设计,功能强大,是操作 MongoDB 的首选 OM 库
  • 因此,在项目中若需要同时对接多种数据库类型,可以采用如下组合:
    • 对关系型数据库使用 TypeORM 或 Prisma
    • 对 MongoDB 使用 Mongoose
  • 项目中使用了 Prisma、TypeORM 和 Mongoose 三种 OM 库
  • 这种组合适用于极端复杂的业务场景(如本地与云端数据同步、多种数据库共存等)

需求与架构设计

  • 在设计之前,先了解需求:
      1. 支持 prisma, typeorm, mongoose 三种类型的库
      1. 支持mysql, postgresql, mongodb 数据库
      1. 租户标识
        • prisma 库
          • prisma1 -> mysql 数据库
          • prisma2 -> postgresql 数据库
        • typeorm 数据库有
          • typeorm1 -> mysql1 数据库
          • typeorm2 -> mysql2 数据库
          • typeorm3 -> postgresql 数据库
        • mongoose
          • mongoose1 -> mongodb1 数据库
          • mongoose2 -> mongodb2 数据库
  • 请按实际业务场景来设计,上面仅作为演示需求,上面表达的是多租户和多数据库的需求
  • 目录设计 (只列举核心目录)
    src
    ├── app.module.ts
    ├── app.controller.ts
    ├── main.ts
    ├── ormconfig.ts
    ├── package.json
    ├── database
    │   ├── database.constants.ts
    │   ├── database.interfaces.ts
    │   ├── database.module.ts
    │   ├── database.utils.ts
    │   ├── prisma
    │   │   ├── prisma-common.module.ts
    │   │   ├── prisma-config.service.ts
    │   │   ├── prisma-core.module.ts
    │   │   ├── prisma-options.interfaces.ts
    │   │   ├── prisma-constants.ts
    │   │   ├── prisma.module.ts
    │   │   └── prisma.utils.ts
    │   ├── typeorm
    │   │   ├── typeorm-common.module.ts
    │   │   ├── typeorm-config.service.ts
    │   │   ├── typeorm.constants.ts
    │   │   └── typeorm.provider.ts
    │   ├── mongoose
    │   │   ├── mongoose-common.module.ts
    │   │   ├── mongoose-config.service.ts
    │   │   ├── mongoose-core.module.ts
    │   │   ├── mongoose.constants.ts
    │   │   ├── mongoose.interfaces.ts
    │   │   ├── mongoose.module.ts
    │   │   ├── mongoose.providers.ts
    │   │   └── mongoose.utils.ts
    ├── user
    │   └── repositories
    │   │   ├── repository.prisma.ts
    │   │   ├── repository.typeorm.ts
    │   │   └── repository.mongoose.ts
    │   ├── user.controller.ts
    │   ├── user.entity.ts
    │   ├── user.interfaces.ts
    │   ├── user.module.ts
    │   ├── user.repository.ts
    │   └── user.schema.ts
    
  • 服务启动的 compose.yaml 文件此处不再提供,因为部署时的服务和相关环境都是不一样的
  • 只提供下面的配置上的地址,仅作演示

租户环境变量.env设计

# prisma 租户1/2
DATABASE_URL="mysql://root:123456_mysql@localhost:13306/testdb" # 这个需要留着, 生成客户端的时候需要此类格式
T_PRISMA1_DATABASE_URL="mysql://root:123456_mysql@localhost:13306/testdb"
T_PRISMA2_DATABASE_URL="postgresql://pguser:123456_postgresql@localhost:15432/testdb"

# typeorm 租户1 配置
T_TYPEORM1_DB_TYPE=mysql
T_TYPEORM1_DB_HOST=localhost
T_TYPEORM1_DB_PORT=13306
T_TYPEORM1_DB_USERNAME=root
T_TYPEORM1_DB_PASSWORD=123456_mysql
T_TYPEORM1_DB_DATABASE=testdb
T_TYPEORM1_DB_AUTOLOAD=true
T_TYPEORM1_DB_SYNC=true

# typeorm 租户2 配置
T_TYPEORM2_DB_TYPE=mysql
T_TYPEORM2_DB_HOST=localhost
T_TYPEORM2_DB_PORT=13307
T_TYPEORM2_DB_USERNAME=root
T_TYPEORM2_DB_PASSWORD=123456_mysql
T_TYPEORM2_DB_DATABASE=testdb
T_TYPEORM2_DB_AUTOLOAD=true
T_TYPEORM2_DB_SYNC=true

# typeorm 租户3 配置
T_TYPEORM3_DB_TYPE=postgres
T_TYPEORM3_DB_HOST=localhost
T_TYPEORM3_DB_PORT=15432
T_TYPEORM3_DB_USERNAME=pguser
T_TYPEORM3_DB_PASSWORD=123456_postgresql
T_TYPEORM3_DB_DATABASE=testdb
T_TYPEORM3_DB_AUTOLOAD=true
T_TYPEORM3_DB_SYNC=true

# mongoose 租户1/2
T_MONGOOSE1_MONGODB_URI="mongodb://root:123456_mongodb@localhost:27018/nestmongodb"
T_MONGOOSE2_MONGODB_URI="mongodb://root:123456_mongodb@localhost:27019/nestmongodb"

根目录下 app.module.ts 模块设计

import {
   
    Module } from '@nestjs/common';
import {
   
    AppController } from './app.controller';
import {
   
    ConfigModule } from '@nestjs/config';
import {
   
    DatabaseModule } from './database/database.module';
import {
   
    UserModule } from './user/user.module';

@Module({
   
   
  imports: [
    ConfigModule.forRoot({
   
     // 配置环境变量模块
      envFilePath: '.env', // 指定环境变量文件路径
      isGlobal: true, // 全局可用
    }),
    DatabaseModule,
    UserModule,
  ],
  controllers: [AppController]
})

export class AppModule {
   
   }

这里,可知,我们把 3种类型的库进行了统一管理,使用 DatabaseModule 来集中管理
UserModule 为我们最终成品的测试模块,从这里可以看到封装的意义

database 模块设计


1 )database/database.module.ts 设计

import {
   
    Module } from '@nestjs/common';
import {
   
    TypeormCommonModule } from './typeorm/typeorm-common.module';
import {
   
    PrismaCommonModule } from './prisma/prisma-common.module';
import {
   
    MongooseCommonModule } from './mongoose/mongoose-common.module';

@Module({
   
   
  imports: [
    TypeormCommonModule,
    PrismaCommonModule,
    MongooseCommonModule
  ],
  providers: [],
  exports: [],
})

export class DatabaseModule {
   
   }
  • TypeormCommonModule
    • 使用 TypeORM 作为 ORM 的公共模块
    • 通常用于关系型数据库(如 PostgreSQL、MySQL)
    • 封装了 TypeORM 的连接配置、实体注册、仓储服务等
  • PrismaCommonModule
    • 使用 Prisma ORM 的公共模块
    • Prisma 是新一代的 Node.js ORM,支持 TypeScript,具有良好的类型推导
    • 通常用于构建类型安全的数据访问层
  • MongooseCommonModule
    • 使用 Mongoose 的公共模块
    • Mongoose 是 MongoDB 的 Node.js 驱动 ORM
    • 适用于非关系型数据库(NoSQL)开发

2 )database/database.constants.ts 设计

export const TYPEORM_DB_CLIENT = 'TYPEORM_DB_CLIENT';
export const PRISMA_DB_CLIENT = 'PRISMA_DB_CLIENT';
export const IS_PRISMA = 'IS_PRISMA';
export const IS_TYPEORM = 'IS_TYPEORM';
export const IS_MONGOOSE = 'IS_MONGOOSE';

3 )database/database.interfaces.ts 设计

export interface ItenantRs {
   
   
    isPrisma: Boolean,<
Nestjs框架: 基于TypeORM的多租户功能集成和优化 本文介绍了如何通过Docker Compose配置多租户数据库环境(包含2个MySQL和1个PostgreSQL实例),并集成到NestJS项目中。首先展示了docker-compose配置文件,详细说明了三个数据库服务的端口映射、数据卷挂载等关键配置。接着通过Adminer工具验证数据库连接并创建测试库。然后重点讲解了TypeORM CLI的配置方法,包括环境变量设置、ORM配置文件编写以及数据库同步脚本的创建。最后提供了针对不同数据库的.env配置示例,并说明了如何执行TypeORM同步命令来初始化数据 阅读详情

相关推荐

nestjs-prisma

nestjs-prisma 描述 这是以下示例存储库: 使用教程 单元测试和端到端测试 GitHub动作和Codecov设置(Badge在README.md) 指示 的入门模板 :smiling_cat_with_heart-eyes: 和 。 检出以自动将Prisma支持添加到您的Nest应用程序中。 版本 分支 巢 棱柱 Graphql 掌握 v7 v6 v6 v6 v5 特征 带GraphQL 带有代码优先 用于数据库建模,迁移和类型安全访问的 (Postgres,MySQL和MongoDB) :locked_with_key: 带JWT身份验证 带有REST API文档 概述 棱镜设置 1.安装依赖项 安装以启动并 npm i -g @nestjs/cli 安装Nest应用程序的依赖项: npm install 2. PostgreSQL与Docker 使用Docker设置开发PostgreSQL。 复制并重命名为.env ,这将为PostgreSQL

nestjs-tenancy:nestjs 的多租户方法 - 目前仅支持 mongodb with mongoose

nestjs-租户 一个简单易用的 NestJs 和 Mongoose 多租户模块 描述 用于多租户模块。 安装 $ npm i --save @needle-innovision/nestjs-tenancy 基本用法 app.module.ts import { Module } from "@nestjs/common" ; import { TenancyModule } from "@needle-innovision/nestjs-tenancy" ; import { CatsModule } from "./cat.module.ts" ; @ Module ( { imports : [ TenancyModule . forRoot ( { tenantIdentifier : 'X-TENANT-ID' , option

全栈Next.js应用平台:一个支持多租户和自定义域的全栈Next.js应用程序的开发平台

一个支持多租户和自定义域的全栈Next.js应用程序的开发平台。它基于Next.js应用路由器和Vercel域API,提供了强大的功能和灵活性,让开发人员可以构建具有多租户和自定义域的全栈应用程序。

MaxEnt物种分布预测中的常见误区与优化技巧:如何提高模型准确率

本文深入探讨了MaxEnt物种分布预测模型从基础应用到精准预测的进阶实践。针对模型准确率提升,文章系统分析了环境变量筛选、模型参数调优、结果批判性解读等核心环节的常见误区,并提供了基于生态位模型原理的深度优化技巧,帮助研究者产出更可靠、可解释的预测结果。

weixin_29219539的博客 595

RuoYi(分离版) 使用代码生成器添加子模块(idea版)

文章目录准备一、使用代码生成器1.数据库2.导入表并生成代码二、导入代码文件1.新建一个模块2.导入zip代码文件3.模块环境配置添加菜单和访问地址总结 准备 前提要把系统启动起来,部分教程可以参考这边文章若依框架RuoYi前后端分离项目导入IDEA及运行启动 但是完全参考这篇文章还是不能把项目启动起来,因为这篇文章没有说明数据库。 我是用的是本地数据库,采用xampp+Navicat的组合来部署和访问数据库。打开Navicat,连接并创建数据库ry-vue并导入数据脚本ry_20191008.sql,q

dream_coke的博客 1万+

DisplayPort 1.4数据扰码实战:16bit LFSR并行优化技巧(附Verilog代码)

本文深入探讨了DisplayPort 1.4协议中16bit数据扰码的并行化实现。针对高带宽视频传输需求,文章详细推导了16位LFSR(线性反馈移位寄存器)的单周期16步并行计算公式,并提供了可直接使用的Verilog代码,解决了传统8bit串行处理吞吐量不足的瓶颈,为高速接口设计提供了关键优化技巧。

y4z5a6b7的博客 259

手把手教你用RV1103+SC3336摄像头DIY一个离线人脸门禁原型

本文详细介绍了如何利用RV1103芯片和SC3336摄像头构建离线人脸门禁系统。从硬件选型到算法优化,再到业务逻辑实现,提供了完整的DIY指南。重点讲解了RetinaFace和FaceNet算法在嵌入式系统中的移植与调优,帮助开发者快速实现高效、隐私安全的门禁解决方案。

weixin_26905487的博客 512

华为防火墙USG6600全流量日志配置指南:从流量监控到NAT日志的完整方案

本文详细介绍了华为USG6600防火墙全流量日志配置方案,涵盖流量监控、NAT日志及安全事件溯源等核心功能。通过精细化配置和性能优化技巧,帮助企业构建高效、合规的日志体系,提升网络安全运维效率。文章特别强调了日志采样与字段过滤的实用方法,适用于高流量环境下的资源优化。

gin88的博客 350

电路板功能测试系统-FCT for PCBA

电路板功能测试系统用于电路板组件(PCBA)的功能测试(FCT),满足自动化大批量生产的要求。  ● 用户根据自己需要定义测试步骤,灵活方便  ● 适合工业自动化大批量生产应用  ● 系统测试精度高,稳定可靠   一、电路板功能测试系统概述 电路板测试过程通常由多个步骤组成,每单个步骤中需要对多个物理量(电压、电流、电阻、频率、波形等)进行测试。在每个步骤测试时

6816

2026 拉勾网:JA4+指纹绕过 + sign逆向 + 动态城市参数,月采集10万+数据实战

2026年拉勾网反爬技术全面升级,采用JA4+ TLS指纹识别、动态sign签名等多维度防护体系。本文提供工业级爬虫解决方案,通过curl_cffi模拟浏览器指纹、逆向sign加密算法、动态生成城市参数三大核心技术,实现高效稳定的数据采集。系统采用分层架构设计,包含任务调度、签名生成、多线程引擎等模块,单月可获取10万+条招聘数据。重点解析了JA4+指纹识别原理、传统方法的局限性,以及通过HMAC-SHA256算法逆向sign参数的完整过程。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 2396

把收款差异从扯皮变成闭环:SAP S/4HANA Dispute Resolution 模块到底解决什么问题?

本文摘要: SAP S/4HANA的争议解决模块(Dispute Resolution)通过标准化流程管理企业应收争议,解决发票与收款差异问题。核心是创建可追踪的Dispute Case工单,明确处理角色(Processor和Manager),并与财务系统联动实现自动清账。系统支持手工/自动创建争议工单,通过动态默认值减少错误,并最终实现争议金额归零的闭环管理。文中给出制造业客户扣款的完整处理案例,并强调组织落地需统一权限与目录。最后提供ABAP代码示例展示如何通过BAPI创建争议工单。(150字)

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 168

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

上一篇: Nestjs框架: 基于Mongodb的多租户功能集成和优化
下一篇: Nestjs框架: 关于 OOP / FP / FRP 编程
Wang's Blog
博客等级 码龄12年 7438粉丝 2422原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值