Nestjs框架: 基于TypeORM的多租户功能集成和优化

从零到一:NestJS实体设计的艺术与科学 本文深入探讨了NestJS实体设计的艺术与科学,从基础理念到高级技巧全面解析。通过TypeORM装饰器、关系映射、生命周期钩子等核心功能,帮助开发者构建高性能、可维护的数据库模型。文章特别强调实体设计在数据完整性、查询效率和代码可维护性三个维度的平衡,并提供了电商平台等实战案例。 阅读详情

概述

  • 我们现在要集成多租户的环境,考虑到使用2个mysql和1个postgresql的数据库
  • 现在要集成到 nestjs 的项目中来,考虑到配置通用和性能的处理

配置docker-compose启动服务


docker-compose.multi.yaml

services:
  mysql:
    image: mysql:8
    container_name: mysql_app
    restart: always
    ports:
      - "13306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=123456_mysql
    volumes:
      # - ./mysql/conf.d:/etc/mysql/conf.d # 默认加载这里的配置
      - ./docker-dbconfig/mysql/data:/var/lib/mysql
      - ./docker-dbconfig/mysql/logs:/var/log/mysql
    networks:
      - light_network

  mysql2:
    image: mysql:8
    container_name: mysql_app2
    restart: always
    ports:
      - "13307:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=123456_mysql
    volumes:
      # - ./mysql/conf.d:/etc/mysql/conf.d # 默认加载这里的配置
      - ./docker-dbconfig/mysql/data2:/var/lib/mysql
      - ./docker-dbconfig/mysql/logs2:/var/log/mysql
    networks:
      - light_network

  postgresql:
    image: postgres:16
    restart: always
    environment:
      POSTGRES_PASSWORD: 123456_postgresql
      POSTGRES_DB: testdb
      POSTGRES_USER: pguser # 注意,不能用 root
    ports:
      - 15432:5432
    volumes:
      - ./docker-dbconfig/postgres/data:/var/lib/postgresql/data
      - ./docker-dbconfig/postgres/logs:/var/log/postgresql
    networks:
      - light_network

  adminer:
    image: adminer:5.3.0
    container_name: adminer_app
    restart: always
    ports:
      - 18080:8080
    networks:
      - light_network

networks:
  light_network:
    external: true

执行 $ docker ps

CONTAINER ID   IMAGE                  COMMAND                   CREATED          STATUS         PORTS                                NAMES
6c8879abf8bd   mysql:8                "docker-entrypoint.s…"   10 seconds ago   Up 9 seconds   33060/tcp, 0.0.0.0:13306->3306/tcp   mysql_app
e8dfd71eab60   mysql:8                "docker-entrypoint.s…"   10 seconds ago   Up 9 seconds   33060/tcp, 0.0.0.0:13307->3306/tcp   mysql_app2
5737bcb3c24e   postgres:16            "docker-entrypoint.s…"   10 seconds ago   Up 9 seconds   0.0.0.0:15432->5432/tcp              hello-nest-postgresql-1
af724225edea   adminer:5.3.0          "entrypoint.sh docke…"   10 seconds ago   Up 9 seconds   0.0.0.0:18080->8080/tcp              adminer_app
  • 这里能看到4个服务,其中3个数据库mysql, mysql2, postgresql 分别为: 13306, 13307, 15432

1 ) 连接 mysql

  • 访问: http://localhost:18080

  • 输入

    • 服务器: mysql
    • 用户名: root
    • 密码: 123456_mysql
  • 连接上之后,创建数据库 testdb

2 )连接另一台 mysql2

  • 输入

    • 服务器: mysql2
    • 用户名: root
    • 密码: 123456_mysql
  • 创建数据库 testdb

3 ) 连接 postgresql

  • 系统选择:PostgreSQL

  • 输入

    • 服务器: postgresql
    • 用户名: pguser
      • 注意这里不能用 root
    • 密码: 123456_postgresql
  • 创建数据库 testdb

配置 TypeORM CLI 命令

  • TypeORM 也是支持配置文件的,参考官网 ormconfig
  • typeorm cli 和之前使用的 eslint 一样,也是支持配置文件的
  • 配置之后,就可以使用 typeorm 提供的 init 方法来初始化数据库了

1 ) 安装依赖和配置

  • $ pnpm add dotenv

  • 配置 ormconfig.ts

    import {
         
          DataSource, DataSourceOptions } from 'typeorm';
    import * as dotenv from 'dotenv';
    import * as fs from 'fs';
    import {
         
          TypeOrmModuleOptions } from '@nestjs/typeorm';
    
    export function getEnv(env: string): Record<string, unknown> | undefined {
         
         
    	if (fs.existsSync(env)) {
         
         
    		return dotenv.parse(fs.readFileSync(env));
    	}
    }
    
    export function buildConnectionOptions(){
         
         
    	const defaultConfig = getEnv('.env');
    	const envConfig = getEnv(`.env.${
           
           process.env.NODE_ENV || 'development'}`);
    	const config = {
         
         ...defaultConfig, ...envConfig };
    	return {
         
         
    		type: config['DB_TYPE'],
    		host: config['DB_HOST'],
    		port: config['DB_PORT'],
    		username: config['DB_USERNAME'],
    		password: config ['DB_PASSWORD'],
    		database: config['DB_DATABASE'],
    		entities: [__dirname + '/**/*.entity{.ts,.js}'],
    		synchronize: Boolean(config['DB_SYNC']),
    		autoLoadEntities: Boolean(config['DB_AUTOLOAD']),
    	} as TypeOrmModuleOptions;
    }
    
    export default new DataSource({
         
         
    	...buildConnectionOptions(),
    } as DataSourceOptions);
    

2 ) 配置脚本并同步

  • 配置 package.json 中的 scripts, 添加如下

    "typeorm": "typeorm-ts-node-commonjs -d ormconfig.ts",
    "typeorm:sync": "npm run typeorm schema:sync"
    
  • 参考官网 using-cli

  • 目前有2个mysql的服务和一个postgresql 的服务

    • mysql 的 .env 配置
      DB_TYPE=mysql
      DB_HOST=localhost
      DB_PORT=13306
      DB_USERNAME=root
      DB_PASSWORD=123456_mysql
      DB_DATABASE=testdb
      DB_AUTOLOAD=true
      DB_SYNC=true
      
    • mysql2 的 .env 配置
      DB_TYPE=mysql
      DB_HOST=localhost
      DB_PORT=13307
      DB_USERNAME=root
      DB_PASSWORD=123456_mysql
      DB_DATABASE=testdb
      DB_AUTOLOAD=true
      DB_SYNC=true
      
    • postgresql 的 .env 配置
      DB_TYPE=postgres
      DB_HOST=localhost
      DB_PORT=15432
      DB_USERNAME=pguser
      DB_PASSWORD=123456_postgresql
      DB_DATABASE=testdb
      DB_AUTOLOAD=true
      DB_SYNC=true
      
  • 对于 postgres 数据库,需要安装依赖 $ pnpm add pg

  • 切换上面的不同 .env 配置,分别执行 $ pnpm run typeorm:sync

  • mysql 的输出

    query: SELECT VERSION() AS `version`
    query: START TRANSACTION
    query: SELECT DATABASE() AS `db_name`
    query: SELECT `TABLE_SCHEMA`, `TABLE_NAME`, `TABLE_COMMENT` FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA` = 'testdb' AND `TABLE_NAME` = 'user' UNION SELECT `TABLE_SCHEMA`, `TABLE_NAME`, `TABLE_COMMENT` FROM `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA` = 'testdb' AND `TABLE_NAME` = 'user'
    query:
                    SELECT
                        *
                    FROM
                        `INFORMATION_SCHEMA`.`COLUMNS`
                    WHERE
                        `TABLE_SCHEMA` = 'testdb'
                        AND
                        `TABLE_NAME` = 'user'
    
    query: SELECT * FROM (
                    SELECT
                        *
                    FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` `kcu`
                    WHERE
                        `kcu`.`TABLE_SCHEMA` = 'testdb'
                        AND
                        `kcu`.`TABLE_NAME` = 'user'
                ) `kcu` WHERE `CONSTRAINT_NAME` = 'PRIMARY'
    query:
                SELECT
                    `SCHEMA_NAME`,
                    `DEFAULT_CHARACTER_SET_NAME` as `CHARSET`,
                    `DEFAULT_COLLATION_NAME` AS `COLLATION`
                FROM `INFORMATION_SCHEMA`.`SCHEMATA`
    
    query:
                SELECT
                    `s`.*
                FROM (
                    SELECT
                        *
                    FROM `INFORMATION_SCHEMA`.`STATISTICS`
                    WHERE
                        `TABLE_SCHEMA` = 'testdb'
                        AND
                        `TABLE_NAME` = 'user'
                ) `s`
                LEFT JOIN (
                    SELECT
                        *
                    FROM `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS`
                    WHERE
                        `CONSTRAINT_SCHEMA` = 'testdb'
                        AND
                        `TABLE_NAME` = 'user'
                ) `rc`
                    ON
                        `s`.`INDEX_NAME` = `rc`.`CONSTRAINT_NAME`
                        AND
                        `s`.`TABLE_SCHEMA` = `rc`.`CONSTRAINT_SCHEMA`
                WHERE
                    `s`.`INDEX_NAME` != 'PRIMARY'
                    AND
                    `rc`.`CONSTRAINT_NAME` IS NULL
    
    query:
                SELECT
                    `kcu`.`TABLE_SCHEMA`,
                    `kcu`.`TABLE_NAME`,
                    `kcu`.`CONSTRAINT_NAME`,
                    `kcu`.`COLUMN_NAME`,
                    `kcu`.`REFERENCED_TABLE_SCHEMA`,
                    `kcu`.`REFERENCED_TABLE_NAME`,
                    `kcu`.`REFERENCED_COLUMN_NAME`,
                    `rc`.`DELETE_RULE` `ON_DELETE`,
                    `rc`.`UPDATE_RULE` `ON_UPDATE`
                FROM (
                    SELECT
                        *
                    FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` `kcu`
                    WHERE
                        `kcu`.`TABLE_SCHEMA` = 'testdb'
                        AND
                        `kcu`.`TABLE_NAME` = 'user'
                ) `kcu`
                INNER JOIN (
                    SELECT
                        *
                    FROM `INFORMATION_SCHEMA`.`REFERENTIAL_CONSTRAINTS`
                    WHERE
                        `CONSTRAINT_SCHEMA` = 'testdb'
                        AND
                        `TABLE_NAME` = 'user'
                
NestJS框架核心优势与Node.js企业级开发实践 Node.js作为流行的服务端运行时,其框架生态持续演进以满足企业级需求。NestJS通过模块化架构和TypeScript深度集成,解决了传统Node框架在代码组织和类型安全方面的痛点。其依赖注入、拦截器等特性显著提升工程效率,特别适合构建高并发的微服务系统。在SaaS多租户场景中,NestJS的数据库隔离策略和请求生命周期管理展现出强大灵活性。结合Fastify适配器和响应压缩等技术,可使QPS提升2.3倍,这些特性使其成为GitHub增长最快的Node框架,每月npm下载量超300万次。 阅读详情

相关推荐

Nestjs框架: 数据库多租户模式与动态模块初探

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

Wang的专栏 1528

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

本文介绍了在NestJS项目中实现多数据库对接的方案,重点解决多租户架构下的数据隔离与灵活切换需求。通过抽象层统一接口,结合TypeORM、Prisma和Mongoose三种ORM库,支持MySQL、PostgreSQL和MongoDB等多种数据库类型。方案采用外观模式+抽象工厂模式+策略模式,通过DatabaseModule集中管理数据库连接,根据租户ID动态切换不同数据库配置。文章详细阐述了环境变量设计、目录结构和模块实现,为复杂业务场景下的多数据库管理提供了可行方案。

Wang的专栏 1789

NestJS与MySQL整合开发实战指南

关系型数据库MySQL作为Web应用最常用的数据存储方案,与Node.js生态的整合一直是开发者关注的重点。TypeORM作为Node.js领域主流的ORM框架,通过装饰器语法和ActiveRecord模式简化了数据库操作。NestJS框架凭借其模块化架构和依赖注入机制,与TypeORM的深度整合为企业级应用提供了完整的数据库访问解决方案。本文以用户管理系统为例,详细演示如何从零配置NestJS+TypeORM+MySQL开发环境,实现包括实体定义、CRUD操作、事务处理等核心功能,并分享连接池优化、索引设

weixin_30251829的博客 398

NestJS:前端开发者快速上手的后端框架

依赖注入(DI)和模块化是现代软件开发的核心概念,它们通过解耦组件依赖关系来提高代码的可维护性和可测试性。在Node.js生态中,NestJS框架将这些原理与TypeScript深度结合,为开发者提供了类似Angular的开发体验。其装饰器语法和模块系统特别适合有前端背景的开发者快速构建企业级后端应用,在REST API开发、微服务架构等场景展现出色表现。通过内置的依赖注入容器和AOP支持,NestJS有效解决了传统Node.js项目在复杂度增长时的架构难题,成为连接前后端开发范式的重要桥梁。

weixin_33672400的博客 503

开源全栈ERP ever-gauzy 实战:部署、定制与评估

企业日常运营往往面临数据孤岛与流程割裂的挑战,ERP系统通过模块化集成打通业务闭环。开源ERP为企业提供低成本、可定制的数字化基础,而全栈TypeScript技术栈则大幅降低二次开发门槛。ever-gauzy正是这样一款融合销售、财务、人力与项目管理的一体化开源系统,其模块化架构与统一数据模型让线索、订单、库存、薪资等环节实时联动。本文基于实际部署经验,分享从环境搭建、种子数据初始化到核心模块体验的完整历程,并针对权限模型、自定义字段、API集成等定制要点给出工程实践建议,帮助技术团队评估其适用性并快速落地

weixin_34199764的博客 292

mongodb_multi_tenancy:使用 Nodejs 和 mongodb 的多租户示例

使用MongoDB和Nodejs演示多租户应用程序 **如何运行? git clone https://github.com/Aijaz12550/mongodb_multi_tenancy.git yarn yarn start ** 如果您可以随意协作并使此示例更有用。 ** 谢谢 **

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

graphql-transform-federation:将现有的GraphQL模式转换为联合模式

graphql-transform-federation 如果要使用,但是无法重建当前的GraphQL架构,则可以使用此转换将GraphQL联合身份验证功能添加到现有模式。 当您使用托管的GraphQL服务或不支持联合(尚未)的生成的架构时,需要使用它。 如果使用的是apollo服务器或其他支持联合身份验证的架构构建器,则不需要此转换,则应直接 。 此转换将添加解析器和指令以符合。 可以重用许多,以确保它符合规范。 请查看的以获取更多背景信息。 用法 您可以在本地或远程GraphQL模式上使用此转换。 使用远程模式时,您的服务将充当中间件层,如上图所示。 请查看,以获取如何获取可用于此

multi-tenant-nestjs

一个渐进式的框架,用于构建高效且可扩展的服务器端应用程序。 描述 框架TypeScript入门资料库。 安装 $ npm install 运行应用 # development $ npm run start # watch mode $ npm run start:dev # production mode $ npm run start:prod 测试 # unit tests $ npm run test # e2e tests $ npm run test:e2e # test coverage $ npm run test:cov 支持 Nest是MIT许可的开源项目。 得益于赞助商和出色支持者的支持,它可以发展壮大。 如果您想加入他们,请。 保持联系 作者 网站-https: 执照 Nest已。

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

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

Klipper-源码模块

Klippy上位机程序采用多线程架构,包含四个主要进程:主线程处理G代码命令、串口IO线程(C语言实现)、MCU响应处理线程(Python实现)和独立日志线程。代码结构分为三大模块:chelper(C语言辅助函数)、extras(扩展功能如温度控制)和kinematics(运动学模型实现)。核心功能模块包括串口通信(serialhdl.py)、步进电机控制(stepper.py)、运动学计算等,其中C语言实现的底层模块通过serialqueue.c处理高效IO。扩展模块支持热床、传感器等外设,运动学子模块提

weixin_44258581的博客 992

【学习体会】Lighttools8.4.0:软件基本使用+光度学基本概念+系统初始设置

关于Lighttools8.4.0软件的安装教程,详见我的另一篇博文:【软件安装】win10下Lighttools8.4.0(64)光学系统建模软件的安装教程 在本文中,我们将学习到,光度学的基本概念、系统初始设置、物体模型坐标的使用方法、简单光学系统实例、系统浏览器的作用和内容、设置虚拟相机并渲染视图中的图像、仿真结果3D显示等。 如果有其他感兴趣的内容但是我又没有写的,欢迎在评论区留言! 光度学的基本概念 软件的基本介绍 参考博文:https://www.docin.c...

LeonJin的博客 2万+

血管分割中的直径平衡难题:从clDice到cbDice的演进与实践

本文探讨了血管分割中的直径平衡难题,详细分析了从clDice到cbDice的技术演进与实践。通过引入半径感知权重和边界对齐惩罚,cbDice在保持拓扑完整性的同时提升了几何敏感度,显著改善了细小血管的分割效果。文章还分享了在nnU-Net中实现cbDice的工程细节,包括GPU加速骨架提取和多任务损失组合策略,为医学影像分析提供了重要参考。

weixin_29170327的博客 244

决策树(分类树、回归树)

决策树 前言:第一篇博客,最近看完决策树,想着归纳一下,也方便自己以后回顾。写的会比较全面一些,可能会有很多不太正确的地方,欢迎大家交流指正 : ) 决策树模型: 决策树模型是运用于分类以及回归的一种树结构。决策树由节点和有向边组成,一般一棵决策树包含一个根节点、若干内部节点和若干叶节点。决策树的决策过程需要从决策树的根节点开始,待测数据与决策树中的特征节点进行比较,并按照比较结果选...

你午睡了吗 9万+

XGBoost算法案例 - 红酒品质分类

数据集共包含 11 个特征,共计 3269 条数据. 我们通过训练模型来预测红酒的品质, 品质共有 6 个各类别,分别使用数字: 0、1、2、3、4、5 来表示。

YIAN爱学习的博客 450

RT-DETR训练前的准备,将数据集划分成训练集、测试集验证集(附完整脚本及使用说明)

在计算机视觉领域,当我们着手训练一个模型时,。其中,将数据集划分为和更是一项基础性且关键的操作。这篇博客分析了这一划分背后的原因、其重要意义以及如何通过代码实现,帮助大家更好地理解和运用这一技巧,。

Limiiiing的博客 912

PostgreSQL:Patroni 高可用架构,基于etcd的自动故障转移集群

本文详细介绍了基于Patroni和etcd构建PostgreSQL高可用集群的方案。Patroni作为外部守护进程,通过etcd分布式协调服务实现自动故障转移、主节点选举等关键功能,弥补了PostgreSQL原生缺乏自动故障转移的不足。文章涵盖核心架构(3节点PG+3节点etcd)、环境规划、etcd集群部署(包括配置验证)以及Patroni安装配置的关键步骤,特别强调了Patroni自动初始化PG实例、配置同步复制等生产级特性。该方案通过外部组件协同工作,在不修改PG源码的情况下实现了生产环境所需的高可用

数据知道的博客 2495

【CASS精品教程】035:南方CASS7.1台阶画法案例大全

摘要:本文详细介绍了南方CASS7.1软件中5种台阶工具的使用方法,包括普通台阶、有边台阶、L型台阶、U型台阶和不规则台阶。重点说明各类台阶的绘制步骤和注意事项,如绘制方向(从右下角逆时针连接4个点)、台阶方向标识(白色边为下边)、台阶数自动生成不可更改等特性。同时指出高版本CASS可能存在操作差异,并配以多张示意图直观展示各类台阶的绘制过程和效果,为使用CASS7.1绘制建筑台阶提供了实用指导。(148字)

智慧空间实验室 2927

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

上一篇: Nestjs框架: 数据库架构设计与 NestJS 多 ORM 动态数据库应用与连接池的配置
下一篇: Nestjs框架: 关于controller中的常用装饰器
Wang's Blog
博客等级 码龄12年 7438粉丝 2421原创
评论
成就一亿技术人!
拼手气红包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、付费专栏及课程。

余额充值