Prisma中同一查询无法更新关联表问题求助
问题:更新Payment状态时无法同时更新关联Wallet余额
我在使用Prisma时,尝试将Payment的状态更新为PAID的同时,在同一个查询里更新关联的Wallet余额,但执行时报错。
Prisma Schema
generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { uid String @id @default(cuid()) created_at DateTime username String roles String[] accessToken String session Session[] walletId String @unique wallet Wallet @relation(fields: [walletId], references: [id]) payment Payment[] } model Session { id String @id @default(uuid()) userid String expires DateTime @db.Timestamptz cookieId String @unique user User @relation(fields: [userid], references: [uid]) } model Wallet { id String @id @default(uuid()) balance Int @default(0) user User? payment Payment[] } model Order { id String @id @default(uuid()) createdAt DateTime @default(now()) product Product @relation(fields: [productId], references: [id]) //Note that only one product can be ordered at a time payment Payment @relation(fields: [paymentId], references: [piPaymentId]) productId String paymentId String @unique } model Payment { piPaymentId String @id @unique amount Float txid String @default("") status PaymentStatus @default(PENDING) user User @relation(fields: [userId], references: [uid]) order Order? wallet Wallet @relation(fields: [walletId], references: [id]) walletId String userId String } model Product { id String @id @default(uuid()) name String price Float amount Int //Note at this moment we only support coins as a product order Order[] } enum PaymentStatus { PENDING PAID FAILED CANCELLED }
正常的Payment创建代码
async create(payment: APIRequests.Paymnet.Create) { return await this.db.prisma.payment.create({ data: { piPaymentId: payment.paymentId, user: { connect: { uid: payment.userId, }, }, amount: payment.amount, status: "PENDING", wallet: { connect: { id: payment.walletId } } } }); }
出错的更新代码
async complete(payment: APIRequests.Paymnet.Complete) { await this.db.prisma.payment.update({ where: { piPaymentId: payment.paymentId }, data: { status: "PAID", txid: payment.txid, wallet: { update: { balance: { decrement: payment.amount } } } } }); }
报错信息
Error: Invalid `prisma.payment.update()` invocation: { where: { piPaymentId: 'some paymentID' }, data: { status: 'PAID', txid: 'some txid', wallet: { ~~~~~~ update: { balance: { decrement: 0.1 } } } } } Unknown arg `wallet` in data.wallet for type PaymentUncheckedUpdateInput. Did you mean `walletId`? Available args: type PaymentUncheckedUpdateInput { piPaymentId?: String | StringFieldUpdateOperationsInput amount?: Float | FloatFieldUpdateOperationsInput txid?: String | StringFieldUpdateOperationsInput status?: PaymentStatus | EnumPaymentStatusFieldUpdateOperationsInput order?: OrderUncheckedUpdateOneWithoutPaymentNestedInput walletId?: String | StringFieldUpdateOperationsInput userId?: String | StringFieldUpdateOperationsInput }
解决方案
核心原因
Prisma的update操作仅支持更新当前模型的字段(含外键字段如walletId),不允许直接通过关联关系字段(如wallet)嵌套更新关联模型。而create操作支持connect/create关联模型,这是两种操作的差异点。
方法1:使用事务(推荐)
通过Prisma事务保证两个操作的原子性,避免部分成功的情况:
async complete(payment: APIRequests.Paymnet.Complete) { // 先获取目标Payment关联的walletId const paymentRecord = await this.db.prisma.payment.findUnique({ where: { piPaymentId: payment.paymentId }, select: { walletId: true } }); if (!paymentRecord) { throw new Error("Payment记录不存在"); } // 执行事务:更新Payment状态 + 更新Wallet余额 await this.db.prisma.$transaction([ this.db.prisma.payment.update({ where: { piPaymentId: payment.paymentId }, data: { status: "PAID", txid: payment.txid } }), this.db.prisma.wallet.update({ where: { id: paymentRecord.walletId }, data: { balance: { decrement: payment.amount } } }) ]); }
方法2:从Wallet端反向更新
如果业务允许,也可以从Wallet模型的update操作中,嵌套更新关联的Payment:
async complete(payment: APIRequests.Paymnet.Complete) { await this.db.prisma.wallet.update({ where: { // 通过关联的Payment筛选目标Wallet payment: { some: { piPaymentId: payment.paymentId } } }, data: { balance: { decrement: payment.amount }, // 嵌套更新关联的Payment状态 payment: { update: { where: { piPaymentId: payment.paymentId }, data: { status: "PAID", txid: payment.txid } } } } }); }
内容的提问来源于stack exchange,提问作者LeVarez
相关产品推荐
相关产品推荐

