• 事务
    • 创建和使用事务
      • 指定隔离级别
    • 事务装饰器
    • 使用 QueryRunner 创建和控制单个数据库连接的状态

    事务

    创建和使用事务

    事务是使用ConnectionEntityManager创建的。 例如:

    1. import { getConnection } from "typeorm";
    2. await getConnection().transaction(transactionalEntityManager => {});

    or

    1. import { getManager } from "typeorm";
    2. await getManager().transaction(transactionalEntityManager => {});

    你想要在事务中运行的所有内容都必须在回调中执行:

    1. import { getManager } from "typeorm";
    2. await getManager().transaction(async transactionalEntityManager => {
    3. await transactionalEntityManager.save(users);
    4. await transactionalEntityManager.save(photos);
    5. // ...
    6. });

    当在事务中工作时需要总是使用提供的实体管理器实例 - transactionalEntityManager。 如果你使用全局管理器(来自getManager或来自连接的 manager 可能会遇到一些问题。 你也不能使用使用全局管理器或连接的类来执行查询。必须使用提供的事务实体管理器执行所有操作。

    指定隔离级别

    指定事务的隔离级别可以通过将其作为第一个参数提供来完成:

    1. import { getManager } from "typeorm";
    2. await getManager().transaction("SERIALIZABLE", transactionalEntityManager => {});

    隔离级别实现与所有数据库不相关。

    以下数据库驱动程序支持标准隔离级别(READ UNCOMMITTEDREAD COMMITTEDREPEATABLE READSERIALIZABLE):

    • MySQL
    • Postgres
    • SQL Server

    SQlite将事务默认为SERIALIZABLE,但如果启用了shared cache mode,则事务可以使用READ UNCOMMITTED隔离级别。

    Oracle仅支持READ COMMITTEDSERIALIZABLE隔离级别。

    事务装饰器

    以下装饰器可以帮助你组织事务操作 - @Transaction, @TransactionManager@TransactionRepository

    @Transaction将其所有执行包装到一个数据库事务中,@TransportManager提供了一个事务实体管理器,它必须用于在该事务中执行查询:

    1. @Transaction()
    2. save(@TransactionManager() manager: EntityManager, user: User) {
    3. return manager.save(user);
    4. }

    隔离级别:

    1. @Transaction({ isolation: "SERIALIZABLE" })
    2. save(@TransactionManager() manager: EntityManager, user: User) {
    3. return manager.save(user);
    4. }

    必须使用@TransportManager提供的管理器。

    但是,你也可以使用@TransactionRepository注入事务存储库(使用事务实体管理器):

    1. @Transaction()
    2. save(user: User, @TransactionRepository(User) userRepository: Repository<User>) {
    3. return userRepository.save(user);
    4. }

    你可以注入内置的 TypeORM 的存储库,如RepositoryTreeRepositoryMongoRepository (使用@TransactionRepository(Entity)entityRepository:Repository<Entity>)或自定义存储库(扩展内置 TypeORM 的存储库类并用@ EntityRepository装饰的类)使用@TransactionRepository() customRepository:CustomRepository

    使用 QueryRunner 创建和控制单个数据库连接的状态

    QueryRunner提供单个数据库连接。 使用查询运行程序组织事务。 单个事务只能在单个查询运行器上建立。 你可以手动创建查询运行程序实例,并使用它来手动控制事务状态。 例如:

    1. import { getConnection } from "typeorm";
    2. // 获取连接并创建新的queryRunner
    3. const connection = getConnection();
    4. const queryRunner = connection.createQueryRunner();
    5. // 使用我们的新queryRunner建立真正的数据库连
    6. await queryRunner.connect();
    7. // 现在我们可以在queryRunner上执行任何查询,例如:
    8. await queryRunner.query("SELECT * FROM users");
    9. // 我们还可以访问与queryRunner创建的连接一起使用的实体管理器:
    10. const users = await queryRunner.manager.find(User);
    11. // 开始事务:
    12. await queryRunner.startTransaction();
    13. try {
    14. // 对此事务执行一些操作:
    15. await queryRunner.manager.save(user1);
    16. await queryRunner.manager.save(user2);
    17. await queryRunner.manager.save(photos);
    18. // 提交事务:
    19. await queryRunner.commitTransaction();
    20. } catch (err) {
    21. // 有错误做出回滚更改
    22. await queryRunner.rollbackTransaction();
    23. }

    QueryRunner中有 3 种控制事务的方法:

    • startTransaction - 启动一个新事务。
    • commitTransaction - 提交所有更改。
    • rollbackTransaction - 回滚所有更改。

    了解有关Query Runner的更多信息。