TypeORMの0.2系で複数のDBを使用する
ORMにTypeORMの0.2系を採用したAPIサーバにて、2つのDBを使用(参照のみ)する設定方法を備忘録として残します。
最新の0.3系では設定方法が異なるようなので、公式ドキュメントをご参照ください。
確認した環境
- TypeORM 0.2.29
- Node.js 14系
- Express.js + TypeScriptのAPIサーバ
データベースの接続設定
TypeORMのConnectionOptionの設定を配列とすることで、複数のDBの設定を書けます。
どのDBを使うか判別する識別子としてnameを付与します。
なお、片方(一つ目)のDBにnameを設定しなくても動作しました。
ormconfig.ts
import { ConnectionOptions } from "typeorm";
const ormconfig: ConnectionOptions[] = [
{
type: "mysql",
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT ?? 3306),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
synchronize: false,
logging: false,
entities: ["src/entities/**/*.ts"],
migrations: ["src/db/migrations/**/*.ts"],
subscribers: ["src/db/subscribers/**/*.ts"],
cli: {
entitiesDir: "src/entities",
migrationsDir: "src/db/migrations",
subscribersDir: "src/db/subscribers",
},
},
{
name: "db2", // 2つ目のDBの識別子
type: "postgres",
host: process.env.DB2_HOST,
port: Number(process.env.DB2_PORT ?? 5432),
username: process.env.DB2_USERNAME,
password: process.env.DB2_PASSWORD,
database: process.env.DB2_DATABASE,
synchronize: false,
logging: false,
schema: process.env.DB2_SCHEMA,
entities: ["src/db2Entities/**/*.ts"],
cli: {
entitiesDir: "src/db2Entities",
},
},
];
export default ormconfig;
今回、2つ目のDBは参照のみ行うため、migrationファイルを作らないように migrations
を指定していません。
また、Entity用のディレクトリを1つ目のDBとディレクトリを分けておきます。
ディレクトリ名は適当です。適切なディレクトリ名でお願いします。
接続設定の読み込み
接続設定の読み込みとしてormconfig.tsで指定した識別子を指定します。
index.ts
import { getConnectionOptions, createConnection } from "typeorm";
import express from "express";
import "reflect-metadata";
const main = async () => {
// 1つ目のDBの接続設定
const connectionOptions = await getConnectionOptions(); // 引数に何も指定しなくても1つ目のDBと接続できる
await createConnection(connectionOptions);
// 2つ目のDBの接続設定
const connectionOptions2 = await getConnectionOptions("db2"); // 引数に2つ目のDBの識別子を指定する
await createConnection(connectionOptions2);
...
Entityの用意
User.ts
import { Entity, Column, PrimaryColumn } from "typeorm";
@Entity()
export default class User {
@PrimaryColumn()
id!: number;
@Column({ type: "varchar" })
name!: string;
}
SQL発行
Repository, EntityManagerどちらも、引数に指定した識別子のDBにSQLを発行できます。
Repository APIを使う場合
const db1Repository = getRepository(User);
const result = await db1Repository.find(); // => 引数に何も指定しない場合、1つ目のDBから取得できる
const db2Repository = getRepository(User, "db2"); // => 第二引数にdb2の識別子を指定
const result = await db2Repository.find(); // => 2つ目のDBから取得できる
EntityManager API を使う場合
await getManager("db2").transaction( // => 引数にdb2の識別子を指定
async (transactionalEntityManager) => {
const result = await transactionalEntityManager.find(User); // => 2つ目のDBから取得できる
}
);
感想
片方の(1つ目の)DBの識別子は省略可能でしたが、サボらずに両方のDBに識別子をつけるべきなんですかね。
既にgetRepository が多く書かれており、全てに設定を入れる必要があるので。。。。。サボらずやります。
ちなみに、TypeORM の0.3系ではormconfigが仕様からdropされており、代わりとなるDataSource を使ったMultiple DBへの接続例が載ってます。
これからTypeORMを使い始める方はこちらを参考としてください。
TypeORMの0.3.x系にバージョンアップするのも大変そうです^^
(BREAKING CHANGES激しくないですか?)
Discussion