Malagu 框架提供了一个装饰器 @Transactional
可以在方式上以声明的方式定义事务的相关行为,Malagu 框架会根据装饰器声明的情况来决定事务的开启、传播、回滚和提交。
@Transactional
装饰器配置选项:
export interface TransactionalOption {
name?: string; // 多数据源链接情况下,指定数据源链接名称,默认为 default
isolation?: IsolationLevel; // 数据库隔离级别
propagation?: Propagation; // 事务的传播行为,支持 Required 和 RequiresNew,默认为 Required
readOnly?: boolean; // 只读,不开启事务,默认为开启事务
}
示例
@Put()
@Transactional()
async modify(@Body() user: User): Promise<void> {
const repo = OrmContext.getRepository(User);
await repo.update(user.id, user);
}
@Transactional 与 OrmContext 关系
Malagu 框架会根据装饰器的配置在方法调用前开启事务(也可能不开启),然后把开启事务的 EntityManager 托管在 OrmContext 上下文中,所以通过 OrmContext 就能够取到框架帮我们开启过事务的 EntityManager,其中 Repository 也是通过托管的 EntityManager 创建的,为了正确的取到 EntityManager,请确保装饰器配置的名称与 OrmContext 获取 EntityMananger 的名称保持一致。方法执行完后,框架根据方法的执行情况,会自动决定事务是提交还是回滚,方法执行出现异常则事务回滚,否则事务提交。
数据库查询
数据库查询大部分情况不需要开启事务,但是您也最好在方式加上 @Transactional
装饰器,然后通过 readonly 配置为 true,让框架为您创建一个不开启事务的 EntityManager。如下:
@Get()
@Transactional({ readOnly: true })
list(): Promise<User[]> {
const repo = OrmContext.getRepository(User);
return repo.find();
}
事务传播行为
目前支持两种事务传播行为:
export enum Propagation {
Required, RequiresNew
}
说明:
- Required 需要开启一个事务,如果上一层方法已经开启过事务,则复用上一个事务,否则开启一个新事务
- RequiresNew 不管上一层方法有没有开启过事务,都开启一个新事物
注意:事务在不同的方法传播的时候,请保证方法之间是同步调用的。比如:
**
...
@Transactional()
async foo(): Promise<void> {
...
await bar(); // 必须加上 await
}
....
...
@Transactional()
async bar(): Promise<void> {
...
}
....