- 创建项目
- Nest 控制器
- nest 配置路由请求数据
- Nest 服务
- Nest 模块
- 配置静态资源
- 配置模板引擎
- Cookie 的使用
- Session 的使用
- 跨域,前缀路径、网站安全、请求限速
- 管道、守卫、拦截器、过滤器、中间件
- 一例看懂中间件、守卫、管道、异常过滤器、拦截器
- 数据验证
- 配置抽离
- 环境配置
- 文件上传与下载
- 实现图片随机验证码
- 邮件服务
- nest 基于 possport + jwt 做登陆验证
- 对数据库的密码加密:md5 和 bcryptjs
- 角色权限
- 定时任务
- 接入 Swagger 接口文档
- nest 连接 Mongodb
- typeORM 操作 Mysql 数据库
- nest 统一处理数据库操作的查询结果
- 数据库实体设计与操作
- typeorm 增删改查操作
- typeorm 使用事务的 3 种方式
- typeorm 一对一关系设计与增删改查
- typeorm 一对多和多对一关系设计与增删改查
- typeorm 多对多关系设计与增删改查
- nest 连接 Redis
- 集成 redis 实现单点登录
- Q:nestJS 注入其他依赖时为什么还需要导入其 module
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
typeorm 使用事务的 3 种方式
typeorm
使用事务的方式有哪些?如何使用?
事务
- 在操作多个表时,或者多个操作时,如果有一个操作失败,所有的操作都失败,要么全部成功,要么全部失
- 解决问题:在多表操作时,因为各种异常导致一个成功,一个失败的数据错误。
例子:银行转账 如果用户 1 向用户 2 转了 100 元,但因为各种原因,用户 2 没有收到,如果没有事务处理,用户 1 扣除的 100 元就凭空消失了 如果有事务处理,只有用户 2 收到 100 元,用户 1 才会扣除 100 元,如果没有收到,则不会扣除。
应用场景
多表的增,删,改操作
nest-typrorm 事务的使用方式
- 使用装饰器,在
controller
中编写,传递给service
使用 - 使用
getManager
或getConnection
,在service
中编写与使用 - 使用
connection
或getConnection
,开启queryRunner
,在service
中编写与使用
方式一:使用装饰器
controller
import { Controller, Post, Body, Param, ParseIntPipe, } from '@nestjs/common'; import { Transaction, TransactionManager, EntityManager } from 'typeorm'; 开启事务第一步:引入 import { UserService } from './user.service-oto'; @Controller('user') export class UserController { constructor(private readonly userService: UserService) { } @Post(':id') @Transaction() 开启事务第二步:装饰接口 async create( @Param('id', new ParseIntPipe()) id: number, @TransactionManager() maneger: EntityManager, 开启事务第三步:获取事务管理器 ) { return await this.userService.create(id, maneger); 开启事务第四步:传递给 service,使用数据库时调用 } }
service
- 这里处理的是 1 对 1 关系:保存头像地址到
avatar
表,同时关联保存用户的id
- 如果你不会 1 对 1 关系,请先去学习对应的知识
import { Injectable } from '@nestjs/common'; import { Repository, EntityManager } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { UsersEntity } from './entities/user.entity'; import { AvatarEntity } from './entities/avatar.entity'; import { ToolsService } from '../../utils/tools.service'; @Injectable() export class UserService { constructor( @InjectRepository(UsersEntity) private readonly usersRepository: Repository<UsersEntity>, @InjectRepository(AvatarEntity) private readonly avatarRepository: Repository<AvatarEntity>, ) { } async create(id: number, manager: EntityManager) { const urlObj = { url: `http://www.dmyxs.com/images/${id}.png`, }; const user = await this.usersRepository.findOne({ id }); 先查找用户,因为要保存用户的 id if (!user) ToolsService.fail('用户 id 不存在'); 找不到用户抛出异常 const avatarEntity = this.avatarRepository.create({ url: urlObj.url }); 创建头像地址的实体 const avatarUrl = await manager.save(avatarEntity); 使用事务保存副表 user.avatar = avatarUrl; 主表和副表建立关系 await manager.save(user); 使用事务保存主表 return '新增成功'; 如果过程出错,不会保存 } }
方式二:使用 getManager 或 getConnection
service
import { Injectable } from '@nestjs/common'; import { Connection, Repository, getManager } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { UsersEntity } from './entities/user.entity'; import { AvatarEntity } from './entities/avatar.entity'; import { ToolsService } from '../../utils/tools.service'; @Injectable() export class UserService { constructor( @InjectRepository(UsersEntity) private readonly usersRepository: Repository<UsersEntity>, private readonly connection: Connection, ) { } async test(id: string) { const urlObj = { url: `http://www.dmyxs.com/images/${id}.png`, }; const user = await this.usersRepository.findOne(id); 先查找用户 if (!user) ToolsService.fail('用户 id 不存在'); 找不到用户抛出异常 //getConnection 的方式:await getConnection().transaction(manager=> {}); //getManager 的方式: const result = await getManager().transaction(async (manager) => { const avatarEntity = manager.create(AvatarEntity, { url: urlObj.url }); 创建头像地址的实体 const avatarUrl = await manager.save(AvatarEntity, avatarEntity); 使用事务保存副表 user.avatar = avatarUrl; 创建关联 return await manager.save(UsersEntity, user); 使用事务保存主表,并返回结果 }); return result; } } { "status": 200, "message": "请求成功", "data": { "id": 1, "createdAt": "2021-04-26T09:58:54.469Z", "updatedAt": "2021-04-28T14:47:36.000Z", "deletedAt": null, "username": "admin", "gender": "male", "age": 18, "status": 1, "avatar": { "url": "http://www.dmyxs.com/images/1.png", "id": 52 } } }
方式三:使用 connection 或 getConnection
service
import { Injectable } from '@nestjs/common'; import { Connection, Repository, getManager } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { UsersEntity } from './entities/user.entity'; import { AvatarEntity } from './entities/avatar.entity'; @Injectable() export class UserService { constructor( @InjectRepository(UsersEntity) private readonly usersRepository: Repository<UsersEntity>, private readonly connection: Connection, ) { } async test(id: string) { const urlObj = { url: `http://www.test.com/images/${id}.png`, }; const user = await this.usersRepository.findOne(id); 先查找用户 if (!user) ToolsService.fail('用户 id 不存在'); 找不到用户抛出异常 const queryRunner = this.connection.createQueryRunner(); 获取连接并创建新的 queryRunner await queryRunner.connect(); 使用我们的新 queryRunner 建立真正的数据库连 await queryRunner.startTransaction(); 开始事务 const avatarEntity = new AvatarEntity(); 创建实体:要保存的数据 avatarEntity.url = urlObj.url; try { const result = await queryRunner.manager 使用事务保存到副表 .getRepository(AvatarEntity) .save(avatarEntity); user.avatar = result; 主表和副表建立连接 const userResult = await queryRunner.manager 使用事务保存到副表 .getRepository(UsersEntity) .save(user); await queryRunner.commitTransaction(); 提交事务 return userResult; 返回结果 } catch (error) { console.log('创建失败,取消事务'); await queryRunner.rollbackTransaction(); 出错回滚 } finally { await queryRunner.release(); 释放 } } }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论