You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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[]
}

问题根源与修复方案

核心问题点

  1. 过早断开数据库连接:在执行findFirst后立刻调用prisma.$disconnect(),导致后续create操作因连接已关闭失败。
  2. 错误访问返回对象属性:Prisma返回的用户对象不存在dataValues字段,直接访问会引发报错。
  3. 未合理管理连接生命周期:未在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 14:07:10