Malagu 框架提供了一个装饰器 @Transactional 可以在方式上以声明的方式定义事务的相关行为,Malagu 框架会根据装饰器声明的情况来决定事务的开启、传播、回滚和提交。

@Transactional

装饰器配置选项:

  1. export interface TransactionalOption {
  2. name?: string; // 多数据源链接情况下,指定数据源链接名称,默认为 default
  3. isolation?: IsolationLevel; // 数据库隔离级别
  4. propagation?: Propagation; // 事务的传播行为,支持 Required 和 RequiresNew,默认为 Required
  5. readOnly?: boolean; // 只读,不开启事务,默认为开启事务
  6. }

示例

  1. @Put()
  2. @Transactional()
  3. async modify(@Body() user: User): Promise<void> {
  4. const repo = OrmContext.getRepository(User);
  5. await repo.update(user.id, user);
  6. }

@Transactional 与 OrmContext 关系

Malagu 框架会根据装饰器的配置在方法调用前开启事务(也可能不开启),然后把开启事务的 EntityManager 托管在 OrmContext 上下文中,所以通过 OrmContext 就能够取到框架帮我们开启过事务的 EntityManager,其中 Repository 也是通过托管的 EntityManager 创建的,为了正确的取到 EntityManager,请确保装饰器配置的名称与 OrmContext 获取 EntityMananger 的名称保持一致。方法执行完后,框架根据方法的执行情况,会自动决定事务是提交还是回滚,方法执行出现异常则事务回滚,否则事务提交。

数据库查询

数据库查询大部分情况不需要开启事务,但是您也最好在方式加上 @Transactional 装饰器,然后通过 readonly 配置为 true,让框架为您创建一个不开启事务的 EntityManager。如下:

  1. @Get()
  2. @Transactional({ readOnly: true })
  3. list(): Promise<User[]> {
  4. const repo = OrmContext.getRepository(User);
  5. return repo.find();
  6. }

事务传播行为

目前支持两种事务传播行为:

  1. export enum Propagation {
  2. Required, RequiresNew
  3. }

说明:

  • Required 需要开启一个事务,如果上一层方法已经开启过事务,则复用上一个事务,否则开启一个新事务
  • RequiresNew 不管上一层方法有没有开启过事务,都开启一个新事物

注意:事务在不同的方法传播的时候,请保证方法之间是同步调用的。比如:
**

  1. ...
  2. @Transactional()
  3. async foo(): Promise<void> {
  4. ...
  5. await bar(); // 必须加上 await
  6. }
  7. ....
  8. ...
  9. @Transactional()
  10. async bar(): Promise<void> {
  11. ...
  12. }
  13. ....