NestJS中如何使用Mongoose启动会话执行事务?调用startSession提示连接断开
报错原因
这个错误出现的根本原因是你直接调用了全局mongoose实例的startSession方法,但NestJS的@nestjs/mongoose包是独立管理数据库连接的,全局mongoose实例并没有建立有效的数据库连接,所以调用会话启动方法时抛出连接断开的错误。
解决步骤
- 第一步:在对应服务中注入NestJS托管的Mongoose连接实例,不要直接使用全局mongoose对象
import { Injectable } from '@nestjs/common'; import { InjectConnection } from '@nestjs/mongoose'; import { Connection, ClientSession } from 'mongoose'; @Injectable() export class AuthService { // 注入当前生效的数据库连接实例 constructor(@InjectConnection() private readonly mongooseConnection: Connection) {} // 其余业务逻辑代码 }
- 第二步:从注入的连接实例启动会话,同时所有数据库操作必须传入session参数才会加入事务,另外事务相关的commit、abort、endSession都是异步方法必须加await
const transactionSession = await this.mongooseConnection.startSession(); transactionSession.startTransaction(); try { const newSignupBody: CreateUserDto = {password: hashedPassword, email, username}; // 操作必须传入session参数,才会被纳入当前事务 const user: User = await this.userService.create(newSignupBody, { session: transactionSession }); // 保存profile的操作同样需要传递session const profile: Profile = await this.profileService.create(user['Id'], signupDto, { session: transactionSession }); const result:AuthResponseDto = this.getAuthUserResponse(user, profile); await transactionSession.commitTransaction(); return result; } catch(err) { await transactionSession.abortTransaction(); throw err; // 抛出错误方便上层逻辑捕获处理 } finally { await transactionSession.endSession(); }
- 第三步:修改对应Service的create方法,支持接收session配置参数,示例如下:
// user.service.ts 示例 async create(createUserDto: CreateUserDto, options?: { session?: ClientSession }) { // 批量create返回数组,所以取第一个元素作为返回值 return this.userModel.create([createUserDto], options).then(res => res[0]); }
额外注意事项
MongoDB事务要求运行环境为副本集或者分片集群,单节点MongoDB不支持事务功能,如果是本地测试请部署单节点副本集,否则调整完上述代码后仍然会触发事务相关报错。
内容的提问来源于stack exchange,提问作者Noobish
相关产品推荐
相关产品推荐

