NestJS关联实体获取用户ID时出现undefined错误,求解决方案
问题:激活钱包时无法读取关联用户的id属性
实体关联定义
User实体
@OneToMany(() => Wallet, wallet => wallet.user) wallets: Wallet[];
Wallet实体
@ManyToOne(() => User, user => user.wallets) user: User;
钱包激活服务代码
async walletActivation(walletId: number): Promise<Boolean> { const wallet = await this.walletsRepo.findOneBy({ id: walletId }) if (!wallet) throw new NotFoundException('Wallet Not Found') wallet.isActive = 0; // 先确保钱包未激活 console.log("------"); const user = await this.usersService.findOneById(wallet.user.id); // 此处报错 if (!user) throw new NotFoundException('User associated with the wallet not found.') if (!user.isVerified) throw new BadRequestException('User account is not verified.') wallet.isActive = 1; await this.walletsRepo.save(wallet); return true; }
控制器端点代码
@Post('activateWallet/:id') async walletActivation(@Param('id') id: string) { try { await this.walletsService.walletActivation(+id); return { message: 'Wallet activated successfully' }; } catch (error) { console.error('Error activating wallet:', error); if (error instanceof NotFoundException) { throw new HttpException('Wallet or user not found', HttpStatus.NOT_FOUND); } else if (error instanceof BadRequestException) { throw new HttpException('User is not verified', HttpStatus.BAD_REQUEST); } else { throw new HttpException('Wallet cannot be activated', HttpStatus.BAD_REQUEST); } } }
错误信息
Error activating wallet: TypeError: Cannot read properties of undefined (reading 'id') at WalletsService.walletActivation (G:\abood\IT\Courses\Projects\NestJS\Wallet System\wallet-system\src\wallets\wallets.service.ts:33:66) at process.processTicksAndRejections (node:internal/process/task_queues:105:5) at async WalletsController.walletActivation (G:\abood\IT\Courses\Projects\NestJS\Wallet System\wallet-system\src\wallets\wallets.controller.ts:32:7)
解决建议
1. 查询钱包时关联加载User实体
问题根源是findOneBy默认不会自动加载关联的user实体,导致wallet.user为undefined。修改查询代码,显式指定加载关联:
// 替换原findOneBy代码 const wallet = await this.walletsRepo.findOne({ where: { id: walletId }, relations: ['user'] // 关联加载user实体 });
或者使用QueryBuilder更灵活:
const wallet = await this.walletsRepo.createQueryBuilder('wallet') .leftJoinAndSelect('wallet.user', 'user') .where('wallet.id = :walletId', { walletId }) .getOne();
2. 增加空值检查(可选但推荐)
即使关联加载后,仍可能存在钱包未关联用户的情况,建议增加检查:
if (!wallet.user) throw new NotFoundException('Wallet has no associated user.'); const user = await this.usersService.findOneById(wallet.user.id);
3. 谨慎使用eager加载(不推荐全局使用)
如果确实需要每次查询Wallet都自动加载User,可以在Wallet实体的@ManyToOne装饰器中添加eager: true,但这种方式会增加不必要的数据库查询,仅在全局需要时使用:
@ManyToOne(() => User, user => user.wallets, { eager: true }) user: User;
内容的提问来源于stack exchange,提问作者AbdelrahmanMurad
相关产品推荐
相关产品推荐

