跳转到主要内容

multiple-data-sources

在一个数据源中使用多个数据库

要在单个数据源中使用多个数据库,可以为每个实体指定数据库名称:

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 dataSource
.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 dataSource
.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 和 MSSQL 数据库。

在单个数据源中使用多个模式

要在应用程序中使用多个模式,只需在每个实体上设置 schema

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 dataSource
.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"."user" "user", "thirdSchema"."photo" "photo"
WHERE "photo"."userId" = "user"."id"

您还可以指定表路径而不是实体:

const users = await dataSource
.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
}

复制

您可以使用 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"
}]
}
}

所有模式更新和写操作都使用 master 服务器执行。 由 find 方法或 select 查询构建器执行的所有简单查询都使用随机的 slave 实例。 由 query 方法执行的所有查询都使用 master 实例。

如果您希望在查询构建器创建的 SELECT 语句中明确使用 master,请使用以下代码:

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

如果您想在原始查询中使用 slave,您还需要明确指定查询运行器。

const slaveQueryRunner = dataSource.createQueryRunner("slave")
try {
const userFromSlave = await slaveQueryRunner.query(
"SELECT * FROM users WHERE id = $1",
[userId],
slaveQueryRunner,
)
} finally {
return slaveQueryRunner.release()
}

请注意,由 QueryRunner 创建的连接需要明确释放。

复制支持 mysql、postgres 和 sql server 数据库。

Mysql 支持深度配置:

{
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"
}
}