Multiple connections

複数の接続を使用

複数のデータベースを使用する為に、異なる接続を作成します。以下の例ではdb1Connection,db2Connectionの2つのデータベースの接続を行っています。

import {createConnections} from "typeorm";

const connections = await createConnections([{
    name: "db1Connection",
    type: "mysql",
    host: "localhost",
    port: 3306,
    username: "root",
    password: "admin",
    database: "db1",
    entities: [__dirname + "/entity/*{.js,.ts}"],
    synchronize: true
}, {
    name: "db2Connection",
    type: "mysql",
    host: "localhost",
    port: 3306,
    username: "root",
    password: "admin",
    database: "db2",
    entities: [__dirname + "/entity/*{.js,.ts}"],
    synchronize: true
}]);

この方法で任意の数のデータベースに接続することができます。各データベースに独自の構成やエンティティ、ORMスコープの設定ができます。

接続ごとに、新しい接続インスタンスが作成されます。 作成する接続ごとに名前を指定する必要があります。

接続オプションは、ormconfigファイルからロードすることもできます。 ormconfigファイルからすべての接続をロードできます。

import {createConnections} from "typeorm";

const connections = await createConnections();

または、名前で作成する接続(db2Connection)を指定できます。

import {createConnection} from "typeorm";

const connection = await createConnection("db2Connection");

接続を操作したり特定の接続を取得するには接続名を指定する必要があります。

import {getConnection} from "typeorm";

const db1Connection = getConnection("db1Connection");
// you can work with "db1" database now...

const db2Connection = getConnection("db2Connection");
// you can work with "db2" database now...

この方法の利点は、異なるログイン資格情報、ホスト、ポート、データベースタイプで複数の接続を構成できることです。 欠点は、複数の接続インスタンスを管理・操作をする必要があることです。

単一の接続で複数のデータベースを使用

複数の接続を作成せずに単一の接続で複数のデータベースを使用する場合は、使用するエンティティごとにデータベース名を指定できます。

import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity({ database: "secondDB" })
export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

}
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity({ database: "thirdDB" })
export class Photo {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    url: string;

}

UserエンティティはsecondDBデータベース内に作成され、PhotoエンティティはthirdDBデータベース内に作成されます。 他のすべてのエンティティは、デフォルトの接続データベースに作成されます。

別のデータベースからデータを選択する場合は、エンティティを提供するだけです。

const users = await connection
    .createQueryBuilder()
    .select()
    .from(User, "user")
    .addFrom(Photo, "photo")
    .andWhere("photo.userId = user.id")
    .getMany(); // userId is not a foreign key since its cross-database request

このコードは、次のSQLクエリを生成します:

SELECT 
  * 
FROM 
  "secondDB"."user" "user", 
  "thirdDB"."photo" "photo" 
WHERE 
  "photo"."userId" = "user"."id"

エンティティの代わりにテーブルのパスを指定することもできます。

const users = await connection
    .createQueryBuilder()
    .select()
    .from("secondDB.user", "user")
    .addFrom("thirdDB.photo", "photo")
    .andWhere("photo.userId = user.id")
    .getMany(); // userId is not a foreign key since its cross-database request

この機能は、MySQLおよびMSSQLlデータベースでのみサポートされています。

単一の接続で複数のスキーマを使用する

アプリケーションで複数のスキーマを使用できます。各エンティティにスキーマを設定するだけです。

import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity({ schema: "secondSchema" })
export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

}
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity({ schema: "thirdSchema" })
export class Photo {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    url: string;

}

UserエンティティはsecondSchemaスキーマ内に作成され、PhotoエンティティはthirdSchemaスキーマ内に作成されます。 他のすべてのエンティティは、デフォルトの接続スキーマに作成されます。

別のスキーマからデータを選択する場合は、エンティティを提供するだけです。

const users = await connection
    .createQueryBuilder()
    .select()
    .from(User, "user")
    .addFrom(Photo, "photo")
    .andWhere("photo.userId = user.id")
    .getMany(); // userId is not a foreign key since its cross-database request

このコードは、次のSQLクエリを生成します:

SELECT 
  * 
FROM 
  "secondSchema"."question" "question", 
  "thirdSchema"."photo" "photo" 
WHERE 
  "photo"."userId" = "user"."id"

エンティティの代わりにテーブルのパスを指定することもできます。

const users = await connection
    .createQueryBuilder()
    .select()
    .from("secondSchema.user", "user") // in mssql you can even specify a database: secondDB.secondSchema.user
    .addFrom("thirdSchema.photo", "photo") // in mssql you can even specify a database: thirdDB.thirdSchema.photo
    .andWhere("photo.userId = user.id")
    .getMany();

この機能は、PostgreSQLおよびMSSQLデータベースでのみサポートされています。 mssqlでは、たとえば次のようにスキーマとデータベースを組み合わせることができます。

import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity({ database: "secondDB", schema: "public" })
export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

}

Replication

TypeORMを使用して読み取り/書き込みレプリケーションをセットアップできます。 レプリケーション接続設定の例:

{
  type: "mysql",
  logging: true,
  replication: {
    master: {
      host: "server1",
      port: 3306,
      username: "test",
      password: "test",
      database: "test"
    },
    slaves: [{
      host: "server2",
      port: 3306,
      username: "test",
      password: "test",
      database: "test"
    }, {
      host: "server3",
      port: 3306,
      username: "test",
      password: "test",
      database: "test"
    }]
  }
}

すべてのスキーマの更新および書き込み操作は、マスターサーバーを使用して実行されます。 検索メソッドまたは選択クエリビルダーによって実行されるすべての単純なクエリは、ランダムスレーブインスタンスを使用しています。

クエリビルダーによって作成されたSELECTで明示的にマスターを使用する場合は、次のコードを使用できます。

const masterQueryRunner = connection.createQueryRunner("master");
try {
    const postsFromMaster = await connection.createQueryBuilder(Post, "post")
        .setQueryRunner(masterQueryRunner)
        .getMany();
} finally {
      await masterQueryRunner.release();
}

QueryRunnerによって作成された接続は、明示的に解放する必要があることに注意してください。

レプリケーションは、MySQLPostgreSQLSQL Serverでサポートされています。

{
  replication: {
    master: {
      host: "server1",
      port: 3306,
      username: "test",
      password: "test",
      database: "test"
    },
    slaves: [{
      host: "server2",
      port: 3306,
      username: "test",
      password: "test",
      database: "test"
    }, {
      host: "server3",
      port: 3306,
      username: "test",
      password: "test",
      database: "test"
    }],
    
    /**
    * If true, PoolCluster will attempt to reconnect when connection fails. (Default: true)
    */
    canRetry: true,

    /**
     * If connection fails, node's errorCount increases.
     * When errorCount is greater than removeNodeErrorCount, remove a node in the PoolCluster. (Default: 5)
     */
    removeNodeErrorCount: 5,

    /**
     * If connection fails, specifies the number of milliseconds before another connection attempt will be made.
     * If set to 0, then node will be removed instead and never re-used. (Default: 0)
     */
     restoreNodeTimeout: 0,

    /**
     * Determines how slaves are selected:
     * RR: Select one alternately (Round-Robin).
     * RANDOM: Select the node by random function.
     * ORDER: Select the first node available unconditionally.
     */
    selector: "RR"
  }
}