状況:
SaaS APIの場合、 スキーマベースのマルチテナンシー を使用します)、つまり、すべての顧客(〜テナント)は独自の schema 同じ(postgres)データベース内で、他の顧客に干渉することなく、各スキーマは同じ基礎となるエンティティモデルで構成されます。
新しい顧客がシステムに登録されるたびに、新しい分離スキーマがデータベース内に自動的に作成されます。つまり、スキーマは実行時に作成され、事前にはわかりません。顧客のスキーマは、顧客のドメインに従って名前が付けられます。
APIに到着するすべてのリクエストについて、JWTからユーザーのテナンシーアフィリエーションを抽出し、このテナントに対して要求されたdb操作を実行するために使用するdbスキーマを決定します。
問題
TypeORM を介して(postgres)データベースへの接続を確立した後(たとえば createConnection を使用)、スキーマを設定する唯一の機会db-操作の場合はcreateQueryBuilder
に頼ることです:
const orders = await this.entityManager
.createQueryBuilder()
.select()
.from(`${tenantId}.orders`, 'order') // <--- setting schema-prefix here
.where("order.priority = 4")
.getMany();
つまり、 EntityManager API を使用するときにスキーマを設定することはできないように見えるため、QueryBuilder
を使用する必要があります(または Repository API )。
ただし、これらのAPIは文字列ベースの構文を使用して「手動で」クエリを作成する必要がないため、作成がはるかに簡単で、必要なコードが少なく、エラーが発生しにくいAPIを使用する必要があります。
質問
TypeORMの場合、EntityManager
またはリポジトリを操作するときに、どういうわけかdb-schemaを設定できますか?
このようなもの?
// 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リポジトリ をインスタンス化する方法はありません。
したがって、スキーマベースのマルチテナンシーのために開発者が残されている唯一の2つのオプションは次のとおりです。
createQueryBuilder
を使用するように戻します(またはquery()
を介してSQLクエリを実行します)。さらなる調査のために、実行時に既存の接続またはリポジトリのスキーマを変更するというアイデアを追跡するTypeORM GitHubの問題をいくつか示します(OPで要求されるものと同様)。
this.photoRepository.useSchema('customer1').find()
のようなものを提案しますgetConnection().changeDefaultSchema('myschema')
のようなものを提案します追伸TypeORMがOPで説明されているアイデアをサポートすることを決定した場合、私はこの答えを更新しようとします。