概述
TypeORM可以通过TypeORM中的forRootAsync方法读取点位文件中的配置信息,随后它会自动加载驱动,以便与各类数据库进行对接Prisma部分依托于PrismaClient,无需手动安装数据库驱动。我们直接扩展PrismaClient就能得到一个PrismaService,进而实现对数据库的读写操作- 至于
Mongoose与 上面两个类似 - 我们的目标是让项目既能与单库对接,也能应对多库场景
关于多租户
- 以用户进入系统为例,
NestJS会读取当前用户的租户信息 - 每个用户都携带不同的标签,不同的标签用于区分读取不同的数据库
- 根据用户标签读取不同数据库的配置信息从而获取不同数据库的实例来操作对应的数据库
- 这时候,就需要依赖 动态模块 (Dynamic Module)
- 动态模块提供一种API, 将一个模块导入到另外一个模块
- 并且定义该模块属性的时候可以 影响到 它的属性和行为
- 动态模块 可以让人非常方便的自定义模块,并且注册和配置它
- 在注册模块的过程中,对其配置,传入参数,注册逻辑进行定制
- 这是分层化编程的思想, AOP 编程
- 单库读取相对简单,而通用框架通常会涵盖单库功能
- 所以,我们着重针对多库场景进行数据库设计
- 要把程序封装起来,通过依赖注入的方式读取配置来定义 url
Prisma 的多租户系统集成
- 之前,我们集成Prisma的时候,是用了一套配置,也就是一个数据库的配置
- 在相关service里面,如下
import { Injectable, OnModuleInit } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit { async onModuleInit() { await this.$connect(); } }- 上面,
PrismaService继承了PrismaClient类,并实现了OnModuleInit这个生命周期方法 - 该方法内部会调用
Prisma的$connect方法来连接对应的数据库
- 上面,
- 如果应用场景需要通过
Prisma操作多个数据库,就不能使用同一套配置 - 因为不同用户可能属于不同租户,所以要以租户为单元,让不同用户读取不同的数据库配置
- 这就引出了一个问题:
Prisma如何动态接收配置? - 参考: accessing-environment-variables-from-the-schema
- 点击第一个 Data sources 跳转到 programmatically-override-a-datasource-url
- 就是用程序的方式,动态的写这个 url, 也就是把 datasouce url 拆分成不同字段,这样的目的就是把 url 拆分成 host, user, password 等字段分开管理
- 生成不同的 PrismaClient 存放到 map 中, 后续,当不同的 用户 过来之后,通过 map 定位到 不同的 PrismaClient 从而操作不同数据库
- 普通的写法只能让
Prisma读取配置文件中的一个数据库,如果要实现动态配置,需要参考 之前TypeOrmModule.forRootAsync的方法 传递给prisma.module.ts,并通过依赖注入的方式将ConfigService注入其中 - 接收到数据后,我们需要将其拼接成
Prisma要求的结构,这就需要了解connectionURLs的格式,通常前面是数据库类型、用户密码、主机和端口,后面可能还有查询参数,参考:connection-urls
如何实现动态模块
- 我们知道
TypeOrmModule.forRoot和TypeOrmModule.forRootAsync都是 Dynamic modules 即动态模块 - 我们探索其源码,如下
import { DynamicModule } from '@nestjs/common'; import { DataSource, DataSourceOptions } from 'typeorm'; import { EntityClassOrSchema } from './interfaces/entity-class-or-schema.type'; import { TypeOrmModuleAsyncOptions, TypeOrmModuleOptions } from './interfaces/typeorm-options.interface'; export declare class TypeOrmModule { static forRoot(options?: TypeOrmModuleOptions): DynamicModule; static forFeature(entities?: EntityClassOrSchema[], dataSource?: DataSource | DataSourceOptions | string): DynamicModule; static forRootAsync(options: TypeOrmModuleAsyncOptions): DynamicModule; } <
1717



被折叠的 条评论
为什么被折叠?



