情况:
对于我们的SaaS API,我们使用schema-based multitenancy,这意味着每个客户(〜租户)在同一个(postgres)数据库中都有自己的单独的schema,而不会干扰其他客户。每个模式都包含相同的基础实体模型。
每次有新客户注册到系统时,都会在数据库中自动创建一个新的隔离模式。这意味着,该架构是在运行时创建的,并且事先未知。客户的架构是根据客户的域命名的。
对于到达我们API的每个请求,我们从JWT中提取用户的租约从属关系,并确定要使用哪个db模式来为此租户执行请求的db-operation。
问题
[通过TypeORM与(postgres)数据库建立连接后(例如,使用createConnection),为数据库操作设置模式的唯一机会是求助于createQueryBuilder
:
const orders = await this.entityManager
.createQueryBuilder()
.select()
.from(`${tenantId}.orders`, 'order') // <--- setting schema-prefix here
.where("order.priority = 4")
.getMany();
这意味着,由于使用QueryBuilder
(或EntityManager API)时似乎无法设置架构,因此我们被迫使用Repository API。
但是,我们希望/需要使用这些API,因为它们更容易编写,需要更少的代码并且也更少出错,因为它们不依赖于使用基于字符串的语法“手动”编写查询。
问题
对于TypeORM,在使用EntityManager
或存储库时是否可以通过某种方式设置db模式?
这样的事情?
// set schema when instantiating manager
const manager = connection.createEntityManager({ schema: tenantDomain });
// should find all matching "order" entities within schema
const orders = manager.find(Order, { priority: 4 })
// should find a matching "item" entity within schema using same manager
const item = manager.findOne(Item, { id: 321 })
注意:
目前,如果不创建新连接,就无法在运行时使用不同的架构实例化TypeORM repositories。
因此,对于基于模式的多租户,开发人员只剩下两个选项:
createQueryBuilder
(或通过query()
执行SQL查询的想法。this.photoRepository.useSchema('customer1').find()
]的东西>getConnection().changeDefaultSchema('myschema')
]的东西>https://docs.nestjs.com/techniques/database#async-configuration
我不是在使用NestJS,而是在阅读文档以决定是否适合我们。我们有一个应用程序,其中只有一些模块的每个租户具有多租户架构,因此对我来说也可以使用TypeOrmModule.forRootAsync(dynamicCreatedDbConfig)
。
如果您有拦截器或中间件,可以在...之前准备dynamicCreatedDbConfig数据,则可能会对您有所帮助。