Next.js 13 API路由中Prisma查询异常的注册接口问题
Next.js 13 API路由用户注册接口Prisma查询故障排查
我在Next.js 13的API路由中实现用户注册接口,用于向数据库创建用户。经排查,除Prisma查询逻辑外其他代码均可正常执行;通过注释Prisma查询并添加日志,确认问题根源在Prisma查询部分。
相关API路由代码
const res = await request.json() console.log(res) const { SECRET } = process.env; const createToken = (username: string, id: number) => { return jwt.sign({ username, id }, SECRET, { expiresIn: "2 days" }); }; console.log('i still work 1.5') try { //@ts-ignore const { username, password }: { username: string; password: string } = res; const foundUser = await prisma.user.findFirst({ where: { username: username }, }); await prisma.$disconnect() console.log('i still work 2') if (foundUser) { return NextResponse.json( { message: "cannot create user", }, { status: 400, } ); } else { console.log('i still work 3') const salt = bcrypt.genSaltSync(10); const hash = bcrypt.hashSync(password, salt); const newUser: any = await prisma.user.create({ data: { username: username, hashedPass: hash, createdAt: new Date(), updatedAt: new Date(), }, }); await prisma.$disconnect() console.log(newUser) const token = createToken(newUser.username, newUser.id); const exp = Date.now() + 1000 * 60 * 60 * 48; return NextResponse.json( { username: newUser.dataValues.username, id: newUser.dataValues.id, token, exp, }, { status: 200, } ); } } catch (err) { return NextResponse.json( { message: err, info: 'hello' }, { status: 400, } ); } }
Prisma模型代码
model Book { id Int @id @default(autoincrement()) title String? @db.VarChar(255) summary String? createdAt DateTime @db.Timestamptz(6) updatedAt DateTime @db.Timestamptz(6) userId Int? users User? @relation(fields: [userId], references: [id]) chapters Chapter[] characters Character[] } model Chapter { id Int @id @default(autoincrement()) num Int? name String? @db.VarChar(255) outline String? createdAt DateTime @db.Timestamptz(6) updatedAt DateTime @db.Timestamptz(6) bookId Int? books Book? @relation(fields: [bookId], references: [id]) } model Character { id Int @id @default(autoincrement()) name String? @db.VarChar(255) role String? @db.VarChar(255) description String? createdAt DateTime @db.Timestamptz(6) updatedAt DateTime @db.Timestamptz(6) bookId Int? books Book? @relation(fields: [bookId], references: [id]) } model User { id Int @id @default(autoincrement()) username String? @db.VarChar(255) hashedPass String? @db.VarChar(255) createdAt DateTime @db.Timestamptz(6) updatedAt DateTime @db.Timestamptz(6) books Book[] }
问题根源与修复方案
核心问题点
- 过早断开数据库连接:在执行
findFirst后立刻调用prisma.$disconnect(),导致后续create操作因连接已关闭失败。 - 错误访问返回对象属性:Prisma返回的用户对象不存在
dataValues字段,直接访问会引发报错。 - 未合理管理连接生命周期:未在
finally块中统一处理连接断开,异常场景下可能导致连接泄漏。
修正后的完整代码
import { NextResponse } from 'next/server'; import jwt from 'jsonwebtoken'; import bcrypt from 'bcrypt'; import prisma from '@/lib/prisma'; // 请根据实际路径导入Prisma客户端 export async function POST(request: Request) { const res = await request.json(); console.log(res); const { SECRET } = process.env; const createToken = (username: string, id: number) => { // 断言SECRET存在,或添加空值判断 return jwt.sign({ username, id }, SECRET!, { expiresIn: "2 days" }); }; console.log('i still work 1.5'); try { const { username, password }: { username: string; password: string } = res; // 检查用户是否已存在 const foundUser = await prisma.user.findFirst({ where: { username }, }); if (foundUser) { return NextResponse.json( { message: "用户已存在,无法创建" }, { status: 400 } ); } console.log('i still work 3'); const salt = bcrypt.genSaltSync(10); const hash = bcrypt.hashSync(password, salt); // 创建新用户 const newUser = await prisma.user.create({ data: { username, hashedPass: hash, createdAt: new Date(), updatedAt: new Date(), }, }); console.log(newUser); const token = createToken(newUser.username!, newUser.id); const exp = Date.now() + 1000 * 60 * 60 * 48; return NextResponse.json( { username: newUser.username, id: newUser.id, token, exp, }, { status: 200 } ); } catch (err) { console.error("注册错误详情:", err); return NextResponse.json( { message: "注册失败", error: (err as Error).message }, { status: 400 } ); } finally { // 确保请求结束后统一断开连接 await prisma.$disconnect(); } }
Prisma模型优化建议
将User模型的时间字段设置为自动生成,避免手动传值:
model User { id Int @id @default(autoincrement()) username String? @db.VarChar(255) hashedPass String? @db.VarChar(255) createdAt DateTime @db.Timestamptz(6) @default(now()) updatedAt DateTime @db.Timestamptz(6) @default(now()) @updatedAt books Book[] }
@default(now()):创建用户时自动设置当前时间为createdAt@updatedAt:更新用户时自动刷新updatedAt字段
内容的提问来源于stack exchange,提问作者noahacla
相关产品推荐
相关产品推荐

