• 多个连接,数据库,模式和主从复制设置
    • 使用多个连接
    • 在单个连接中使用多个数据库
    • 在单个连接中使用多个模式
    • 主从复制

    多个连接,数据库,模式和主从复制设置

    使用多个连接

    使用多个数据库的最简单方法是创建不同的连接:

    1. import {createConnections} from "typeorm";
    2. const connections = await createConnections([{
    3. name: "db1Connection",
    4. type: "mysql",
    5. host: "localhost",
    6. port: 3306,
    7. username: "root",
    8. password: "admin",
    9. database: "db1",
    10. entities: [__dirname + "/entity/*{.js,.ts}"],
    11. synchronize: true
    12. }, {
    13. name: "db2Connection",
    14. type: "mysql",
    15. host: "localhost",
    16. port: 3306,
    17. username: "root",
    18. password: "admin",
    19. database: "db2",
    20. entities: [__dirname + "/entity/*{.js,.ts}"],
    21. synchronize: true
    22. }]);

    此方法允许你连接到已拥有的任意数量的数据库,每个数据库都有自己的配置,自己的实体和整体ORM范围和设置。

    对于每个连接,将创建一个新的Connection实例。 你必须为创建的每个连接指定唯一的名称。

    也可以从ormconfig文件加载所有连接选项:

    1. import {createConnections} from "typeorm";
    2. const connections = await createConnections();

    指定要按名称创建的连接:

    1. import {createConnection} from "typeorm";
    2. const connection = await createConnection("db2Connection");

    使用连接时,必须指定连接名称以获取特定连接:

    1. import {getConnection} from "typeorm";
    2. const db1Connection = getConnection("db1Connection");
    3. // 现在可以使用"db1"数据库...
    4. const db2Connection = getConnection("db2Connection");
    5. // 现在可以使用"db2"数据库...

    使用此方法的好处是你可以使用不同的登录凭据,主机,端口甚至数据库类型来配置多个连接。

    但是缺点可能是需要管理和使用多个连接实例。

    在单个连接中使用多个数据库

    如果你不想创建多个连接,但是想在一个连接中使用多个数据库,则可以指定使用的每个实体的数据库名称:

    1. import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
    2. @Entity({ database: "secondDB" })
    3. export class User {
    4. @PrimaryGeneratedColumn()
    5. id: number;
    6. @Column()
    7. firstName: string;
    8. @Column()
    9. lastName: string;
    10. }
    1. import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
    2. @Entity({ database: "thirdDB" })
    3. export class Photo {
    4. @PrimaryGeneratedColumn()
    5. id: number;
    6. @Column()
    7. url: string;
    8. }

    user实体将在secondDB数据库内创建,Photo实体则在thirdDB数据库内。

    如果要从其他数据库中选择数据,则只需提供一个实体:

    1. const users = await connection
    2. .createQueryBuilder()
    3. .select()
    4. .from(User, "user")
    5. .addFrom(Photo, "photo")
    6. .andWhere("photo.userId = user.id")
    7. .getMany(); // userId因其跨数据库请求而不是外键

    此代码将生成以下sql查询(取决于数据库类型):

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

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

    1. const users = await connection
    2. .createQueryBuilder()
    3. .select()
    4. .from("secondDB.user", "user")
    5. .addFrom("thirdDB.photo", "photo")
    6. .andWhere("photo.userId = user.id")
    7. .getMany(); // userId因其跨数据库请求而不是外键

    仅在mysql和mssql数据库中支持此功能。

    在单个连接中使用多个模式

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

    1. import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
    2. @Entity({ schema: "secondSchema" })
    3. export class User {
    4. @PrimaryGeneratedColumn()
    5. id: number;
    6. @Column()
    7. firstName: string;
    8. @Column()
    9. lastName: string;
    10. }
    1. import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
    2. @Entity({ schema: "thirdSchema" })
    3. export class Photo {
    4. @PrimaryGeneratedColumn()
    5. id: number;
    6. @Column()
    7. url: string;
    8. }

    user实体将在secondSchema schema中创建,photo实体将在thirdSchema schema中创建。

    其他实体将在默认连接架构中创建。

    如果要从其他模式中选择数据,则只需提供一个实体:

    1. const users = await connection
    2. .createQueryBuilder()
    3. .select()
    4. .from(User, "user")
    5. .addFrom(Photo, "photo")
    6. .andWhere("photo.userId = user.id")
    7. .getMany(); // userId因其跨数据库请求而不是外键

    此代码将生成以下sql查询(取决于数据库类型):

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

    你还可以指定表而不是实体:

    1. const users = await connection
    2. .createQueryBuilder()
    3. .select()
    4. .from("secondSchema.user", "user") // 在mssql中,指定数据库:secondDB.secondSchema.user
    5. .addFrom("thirdSchema.photo", "photo") // 在mssql中,指定数据库:thirdDB.thirdSchema.photo
    6. .andWhere("photo.userId = user.id")
    7. .getMany();

    仅在postgres和mssql数据库中支持此功能。

    在mssql中,你还可以组合模式和数据库,例如:

    1. import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
    2. @Entity({ database: "secondDB", schema: "public" })
    3. export class User {
    4. @PrimaryGeneratedColumn()
    5. id: number;
    6. @Column()
    7. firstName: string;
    8. @Column()
    9. lastName: string;
    10. }

    主从复制

    你可以使用TypeORM设置读/写复制。

    复制连接设置示例:

    1. {
    2. type: "mysql",
    3. logging: true,
    4. replication: {
    5. master: {
    6. host: "server1",
    7. port: 3306,
    8. username: "test",
    9. password: "test",
    10. database: "test"
    11. },
    12. slaves: [{
    13. host: "server2",
    14. port: 3306,
    15. username: "test",
    16. password: "test",
    17. database: "test"
    18. }, {
    19. host: "server3",
    20. port: 3306,
    21. username: "test",
    22. password: "test",
    23. database: "test"
    24. }]
    25. }
    26. }

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

    如果要在查询构建器创建的SELECT中显式使用master,可以使用以下代码:

    1. const masterQueryRunner = connection.createQueryRunner("master");
    2. try {
    3. const postsFromMaster = await connection.createQueryBuilder(Post, "post")
    4. .setQueryRunner(masterQueryRunner)
    5. .getMany();
    6. } finally {
    7. await masterQueryRunner.release();
    8. }

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

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

    Mysql支持深度配置:

    1. {
    2. replication: {
    3. master: {
    4. host: "server1",
    5. port: 3306,
    6. username: "test",
    7. password: "test",
    8. database: "test"
    9. },
    10. slaves: [{
    11. host: "server2",
    12. port: 3306,
    13. username: "test",
    14. password: "test",
    15. database: "test"
    16. }, {
    17. host: "server3",
    18. port: 3306,
    19. username: "test",
    20. password: "test",
    21. database: "test"
    22. }],
    23. /**
    24. * 如果为true,则PoolCluster将在连接失败时尝试重新连接。 (默认值:true)
    25. */
    26. canRetry: true,
    27. /**
    28. * 如果连接失败,则节点的errorCount会增加。
    29. * 当errorCount大于removeNodeErrorCount时,删除PoolCluster中的节点。 (默认值:5)
    30. */
    31. removeNodeErrorCount: 5,
    32. /**
    33. * 如果连接失败,则指定在进行另一次连接尝试之前的毫秒数。
    34. * 如果设置为0,则将删除节点,并且永远不会重复使用。 (默认值:0)
    35. */
    36. restoreNodeTimeout: 0,
    37. /**
    38. * 确定如何选择从库:
    39. * RR:交替选择一个(Round-Robin)。
    40. * RANDOM: 通过随机函数选择节点。
    41. * ORDER: 无条件选择第一个
    42. */
    43. selector: "RR"
    44. }
    45. }