情况:
对于我们的SaaS API,我们使用基于模式的多租户,这意味着每个客户(~租户)在同一个(postgres)数据库中拥有自己独立的模式,不会干扰其他客户。每个模式都由相同的底层实体模型组成。
每当系统注册新客户时,就会在数据库中自动创建一个新的隔离模式。这意味着,该模式是在运行时创建的,而事先不知道。客户的模式名称根据客户的域名命名。
对于到达我们的API的每个请求,我们从JWT中提取用户的租户关联,并确定要使用哪个db模式来执行此租户的请求的db操作。
问题
在通过TypeORM(例如使用createConnection)建立与(postgres)数据库的连接后,我们唯一可以设置db操作的模式的机会是诉诸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或repositories时设置数据库模式?
例如这样:
// 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 })
注意:
- 需要以请求范围的方式设置db-schema,以避免为其他客户的请求设置模式。设置整个连接的模式不是一个选项。
- 我们知道可以创建一个全新的连接并为该连接设置模式,但我们希望重用现有的连接。因此,仅创建新连接以设置模式不是一个选项。