事务
事务具有四个基本特征:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Duration),简称ACID
- 原子性
- 事务必须是一个原子的操作序列单元
- 事务中包含的各项操作在一次执行过程中,只允许出现两种状态之一,要么都成功,要么都失败
- 任何一项导致错误的操作都会导致整个事务的失败,同时其它已经被执行的操作都将被撤销并回滚,只有所有的操作全部成功,整个事务才算是成功完成
- 一致性
- 事务的执行不能破坏数据库数据的完整性和一致性
- 一个事务在执行之前和执行之后,数据库都必须处以一致性状态
- 隔离性
- 在并发环境中,并发的事务是互相隔离的,一个事务的执行不能被其它事务干扰
- 不同的事务并发操作相同的数据时,每个事务都有各自完整的数据空间
- 事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务是不能互相干扰的
- 持久性
- 事务一旦提交后,数据库中的数据必须被永久的保存下来
- 即使服务器系统崩溃或服务器宕机等故障,只要数据库重启,那么一定能够将其恢复到事务成功结束后的状态
案例
魔理沙给灵梦转账514块的步骤:
- 魔理沙的余额-514
- 灵梦的余额+514
只要其中任何一个步骤失败了都算失败,更严重的是,如果步骤2失败了,相当于灵梦什么都没拿到,而魔理沙亏了514块
所以,需要保证转账的操作是一件事务
DTO:
1 2 3 4 5 6 7 8 9 10 11
| export class CreateManagerDto { name: string; money: number; }
export class giveMoneyDto { fromId: number; toId: number; money: number; }
|
实体:
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity() export class Manager { @PrimaryGeneratedColumn() id: number;
@Column() name: string;
@Column() money: number; }
|
Controller:
1 2 3 4 5
| @Post('/giveMoney') giveMoney(@Body() giveMoneyDto: giveMoneyDto) { return this.managerService.giveMoney(giveMoneyDto); }
|
Service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| import { Injectable } from '@nestjs/common'; import { CreateManagerDto, giveMoneyDto } from './dto/create-manager.dto'; import { UpdateManagerDto } from './dto/update-manager.dto'; import { InjectRepository } from '@nestjs/typeorm'; import { Manager } from './entities/manager.entity'; import { Repository } from 'typeorm';
@Injectable() export class ManagerService { constructor( @InjectRepository(Manager) private readonly money: Repository<Manager>, ) {}
async giveMoney(giveMoneyDto: giveMoneyDto) { console.log(giveMoneyDto); try { return this.money.manager.transaction(async (m) => { const from = await this.money.findOne({ where: { id: giveMoneyDto.fromId, }, }); const to = await this.money.findOne({ where: { id: giveMoneyDto.toId, }, }); if (from.money >= giveMoneyDto.money) { m.save(Manager, { id: giveMoneyDto.fromId, money: from.money - giveMoneyDto.money, }); m.save(Manager, { id: giveMoneyDto.toId, money: to.money + giveMoneyDto.money, }); return '转账成功'; } else { return '余额不足,无法发起转账'; } }); } catch (e) { throw new Error(e); } }
}
|