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

GraphQL+React+Prisma创建UUID为ID带嵌套数组用户的方法

实现方案

现有代码问题梳理

  • Prisma 模型未配置 UUID 自动生成,手动传 ID 易出现冲突、伪造问题
  • Resolver 参数顺序错误,Prisma 客户端调用方式不符合 ORM 规范,误用数组原生find/filter方法做数据库查询
  • GraphQL Schema 与 Prisma 模型字段命名、非空约束不匹配,关联查询逻辑冗余
  • Context 配置为静态对象,存在跨请求状态污染风险

分步修改实现

1. 更新 Prisma 模型配置(schema.prisma)

给两个模型的主键配置 UUID 自动生成规则,修正关联约束:

datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

generator client {
  provider = "prisma-client-js"
}

model Inputdata {
  id          String   @id @default(uuid())
  createdAt   DateTime @default(now())
  question    String
  answer      String
  enteredBy   User?    @relation(fields: [enteredById], references: [id], onDelete: Cascade)
  enteredById String?
}

model User {
  id        String      @id @default(uuid())
  inputdata Inputdata[]
}

修改完成后执行命令同步数据库结构:
npx prisma migrate dev --name add_uuid_default


2. 更新 GraphQL Schema(schema.graphql)

移除创建用户时的前端传 ID 要求,对齐字段非空约束:

type Query {
    info: String!
    feed: [Inputdata!]!
    user(id:ID!): User!
}
type Mutation {
  post(question: String!, answer: String!, userId: ID): Inputdata!
  createUser: User!
}
type Inputdata {
  id: ID!
  question: String!
  answer: String!
  enteredById: ID
}
type User{
  id:ID!
  data: [Inputdata!]!
}

3. 修正 Resolver 逻辑(index.js)

修复参数顺序、Prisma 调用方法,创建用户时无需手动传 ID,UUID 会自动生成:

const fs = require('fs');
const path = require('path');
const { ApolloServer } = require('apollo-server');
const { PrismaClient } = require('@prisma/client');

const resolvers = {
  Query: {
    info: () => `This is the API of the Questionaire app`,
    feed: async (parent, args, context) => {
      return context.prisma.inputdata.findMany();
    },
    user: async (parent, args, context) => {
      if(!args.id){
        throw new Error('id required')
      }
      const user = await context.prisma.user.findUnique({
        where: { id: args.id },
        include: { inputdata: true }
      })
      if(!user) throw new Error('用户不存在')
      return user
    }
  },
  User: {
    data: (parent) => parent.inputdata
  },
  Mutation: {
    post: async (parent, args, context) => {
      return context.prisma.inputdata.create({
        data: {
          question: args.question,
          answer: args.answer,
          enteredById: args.userId || undefined
        },
      })
    },
    createUser: async (parent, args, context) => {
      return context.prisma.user.create({
        data: {}
      })
    }
  }
}

const prisma = new PrismaClient()

const server = new ApolloServer({
    typeDefs: fs.readFileSync(
        path.join(__dirname, 'schema.graphql'),
        'utf8'
    ),
  resolvers,
  context: () => ({ prisma })
})
server
  .listen()
  .then(({ url }) =>
    console.log(`Server is running on ${url}`)
  );

4. React 端调用示例

创建用户时无需传参,拿到服务端返回的 UUID 后存在本地即可,后续提交答案、查询用户数据都复用该 ID:

import { gql, useMutation } from '@apollo/client';

const CREATE_USER = gql`
  mutation CreateUser {
    createUser {
      id
      data {
        id
        question
        answer
      }
    }
  }
`

// 组件内调用
const [createUser] = useMutation(CREATE_USER, {
  onCompleted: (res) => {
    localStorage.setItem('userId', res.createUser.id)
  }
})

注意事项

  • 禁止前端传入用户 ID,服务端自动生成 UUID 可避免 ID 冲突、越权访问问题
  • 所有数据库操作必须使用 Prisma Client 提供的查询 API,不要用 JS 数组方法过滤全表数据,否则会有严重性能问题
  • GraphQL Resolver 参数顺序固定为(parent, args, context, info),顺序错误会导致拿不到对应实例
  • 关联数据优先用 Prisma 的include参数一次性联表查询,比单独写关联 Resolver 性能更高

内容的提问来源于stack exchange,提问作者simonroof

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 20:01:19