后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载本篇技术指南以 Prisma 1.x 的官方参考文档《GraphQL Server Development》为核心脉络结合本仓库prisma1中prisma-client-lib、prisma-yml等包的源码实现系统讲解 GraphQL 服务端开发的核心机制如何用 SDL 定义 API 模式、如何用 Resolver 实现模式、以及 Prisma 如何借助GraphQL bindings将写数据库访问逻辑简化为一两行代码并给出数据库层与应用层两层 GraphQL API 的架构全貌。读完本文你将掌握基于 Prisma 的 schema-driven 开发流程并能独立搭建一个可运行的 GraphQL 服务端。核心起点每一个 GraphQL API 都源自 GraphQL Schema在深入 Prisma 之前需要先建立 GraphQL 服务端开发的最基本心智模型一切 API 能力都来自 schema。Schema 中的类型定义了 API 的操作每个 GraphQL API 的核心都是一份GraphQL schema它用一套专用的语法——Schema Definition LanguageSDL——清晰地声明 API 所有可用的操作和数据类型。SDL 简洁、精炼、易于上手。例如用 SDL 定义一个拥有id和name两个字段的User类型type User { id: ID! name: String! }每个 GraphQL schema 都有三个特殊的根类型root types分别是Query、Mutation和Subscription。这三个根类型上的字段定义了 API 接受的操作。以下面这个 schema 为例type Query { users: [User!]! } type Mutation { createUser(name: String!): User! }由该 schema 定义的 GraphQL API 允许以下两种操作# query list of users query { users { id name } } # create new user mutation { createUser(name: Sarah) { id } }一个查询query或变更mutation中所有字段及其参数的集合被称为该操作的selection set选择集。根字段是 API 的入口点根类型上的字段也叫做根字段root fields它们是 API 的入口点entry-points——任何发送到 API 的 query 或 mutation都必须以某个根字段开头。根字段的类型决定了查询的 selection set 中还能继续包含哪些字段。在上面的例子中根字段的类型是User和[User!]!两种情况下都可以继续选择User类型的任意字段。如果根字段是标量类型selection set 中就无法再嵌套任何字段。例如type Query { hello: String! }这个 API 只接受唯一一种操作query { hello }从源码层面看根类型与字段的这套规则被prisma-client-lib直接依赖在 Client.ts 的构造函数中客户端会用buildSchema(typeDefs)把 SDL 文本解析成可执行的GraphQLSchema对象随后buildMethods()依据 schema 中的根字段动态构建出query、mutation、$subscribe等可调用方法——这正是根字段定义入口点在运行时层面的体现。Resolver 函数把 schema 变成可执行的实现结构与行为的分离GraphQL 明确区分了结构structure与行为behaviourSDL schema 只描述 API 的抽象结构具体的实现则由resolver 函数完成。schema 定义 resolver 实现的组合通常被称为executable schema可执行 schema。schema 中的每一个字段都由一个 resolver 函数支撑——也就是说resolver 的数量与 schema 中的字段数量完全相等包括非根类型的字段。resolver 的职责就是为其对应字段取回数据例如users根字段的 resolver 知道如何获取用户列表。于是 GraphQL 的查询解析过程本质上就是按查询中包含的字段依次调用各自的 resolver 函数因为每个 resolver 都返回其字段的数据。Resolver 函数的四元结构一个 resolver 函数总是按顺序接收四个参数parent有时也叫root查询由 GraphQL 引擎解析引擎会为查询中包含的字段调用 resolver。由于查询可能包含嵌套字段resolver 的执行会存在多个层级。parent参数始终代表上一次resolver 调用的返回值。args该字段可能携带的参数例如上面createUsermutation 中User的name。context一个在 resolver 链中贯穿传递的对象每个 resolver 都可以读写它本质上是 resolver 之间通信、共享信息的媒介。info查询或 mutation 的 AST 表示包含查询的详细结构信息可据此实现更精细的控制。下面是针对上文 schema 的一种可能的 resolver 实现假设存在一个提供数据库访问接口的全局对象dbconst Query { users: (parent, args, context, info) { return db.users() } } const Mutation { createUser: (parent, args, context, info) { return db.createUser(args.name) } } const User { id: (parent, args, context, info) parent.id, name: (parent, args, context, info) parent.name, }上面的 schema 恰好有四个字段这段实现也提供了对应的四个 resolver 函数。注意User类型的 resolver 实际上可以省略——它们的实现过于平凡GraphQL 执行引擎会自动推断。在真实项目中resolver 面临的最大难点正如上面例子所示实现 GraphQL 服务器的主要工作围绕定义 schema和实现对应 resolver展开这也被称为schema-driven development模式驱动开发。实现 resolver 时你需要连接某种数据源来获取响应数据。这个数据源可以是任何东西——数据库SQL 或 NoSQL、REST API、第三方服务甚至某种遗留系统。真实世界远没有全局db对象这么简单特别是 GraphQL 查询可以深度嵌套把这种嵌套查询翻译成 SQL或其他数据库 API既繁琐又极易出错。Prisma 如何简化 GraphQL 服务端开发Resolver 变成一行代码委托模式使用 Prisma 时核心思路是resolver 不再直接访问数据库而是把传入查询的执行权委托delegate给底层的 Prisma 引擎。因此大多数 resolver 的实现都会简化为一行代码而把传入查询翻译成数据库 API的重活全部由 Prisma 完成。这一机制依靠GraphQL bindings实现通过调用 JavaScript或你后端所用的任何编程语言中的专用函数即可与 Prisma GraphQL API 交互。采用这种方案后resolver 的实现会变得和上面假想的db示例一样简单。从源码看这个委托链路在 Client.ts 中完整可见调用 binding 函数后客户端进入processInstructions流程先通过generateSelections生成字段选择再由getDocumentForInstructions组装成 GraphQL AST document然后经execute发送请求最后extractPayload从响应中解包出业务数据。整个过程对开发者透明你看到的只是简单的函数调用。一个真实的 resolver 委派示例在官方配套的 03-Architecture.md 中给出了博客应用场景下的完整 resolver 实现——每个 resolver 都通过context.db直接委托给 Prismaconst resolvers { Query: { feed: (parent, args, context, info) { return context.db.query.posts({ where: { published: true } }, info) }, post: (parent, args, context, info) { return context.db.query.post({ where: { id: args.id } }, info) }, }, Mutation: { createDraft: (parent, args, context, info) { return context.db.mutation.createPost( { data: { title: args.title, published: false, }, }, info, ) }, publish: (parent, args, context, info) { return context.db.mutation.updatePost( { where: { id: args.id }, data: { published: true }, }, info, ) }, deletePost: (parent, args, context, info) { return context.db.mutation.deletePost({ where: { id: args.id } }, info) }, }, }这里的context.db就是一个 Prisma binding 实例它被挂载到 resolver 的context上context正是四参数之一。当调用context.db.query.posts(...)这类函数时binding 实例会在底层组装出对应的 GraphQL 查询并通过 HTTP 发送给 Prisma。GraphQL bindings更好的 ORM用编程语言函数发送 query 与 mutationGraphQL bindings 在一定程度上可以与传统 ORM 类比它允许你用编程语言中的函数与 GraphQL API 通信而不用手工拼装发送给 API 的原始查询字符串。以上文createUsermutation 为例。传统方式下你需要把整个 mutation 拼成字符串mutation { createUser(name: Sarah) { id } }然后把它放进 HTTP POST 请求的body中这是大多数 GraphQL 服务端实现的常见做法发送给 API。这个方案的重大缺陷是查询以字符串形式存在GraphQL 最核心的优势之一——强类型系统——完全没有被利用。GraphQL bindings 改变了这一切通过调用与 schema 根字段同名的专用函数即可发送 query/mutation无需手动拼字符串、走 HTTP。上面的createUsermutation 可以这样发送binding.mutation.createUser({ name: Sarah }, { id })users查询同样可以转成函数调用binding.query.users({}, { id name })可以看到这些函数调用的第一个参数是携带 query/mutation参数的对象第二个参数是决定响应中包含哪些数据的selection set。调用时binding实例会在底层负责把操作翻译成 GraphQL 查询、发送给服务器并把响应以编程语言对象的形式返回。静态绑定 vs 动态绑定Bindings 有两种形态静态static与动态dynamic。静态绑定用于从静态强类型语言如 TypeScript、Scala交互 GraphQL API——这些语言要求所有表达式的类型在编译期已知。此时 binding 函数在构建期通过代码生成code generation产生所有函数调用都能被编译器校验拼写错误以及结构错误如传错参数类型在编译期就被捕获。另一个优势是编辑器可以辅助你发起 API 请求例如对可用操作和查询参数提供自动补全这对后端开发体验是质的提升——不再有脆弱的 SQL 字符串或数据库 API而是通过强类型层与数据库交互。动态绑定常用于动态编程语言如 JavaScript不需要额外的构建步骤。binding实例上的方法调用只在运行时才翻译成 GraphQL 查询但仍保留了简洁的 binding 语法这一核心优势构建期错误检查与自动补全则可以通过合适的构建工具达成。源码佐证prisma-client-lib 中的两套生成器静态绑定靠代码生成这一点在仓库中有直接实现证据。prisma-client-lib的 codegen/generators 目录下同时存在 TypeScript、JavaScript、Flow、Go 等语言的生成器并在 index.ts 中统一导出。以 TypeScript 生成器为例typescript-client.ts 中定义了 GraphQL 标量与 TS 类型的映射表scalarMapping { Int: number, String: string, ID: string | number, Float: number, Boolean: boolean, DateTimeInput: Date | string, DateTimeOutput: string, Json: any, }同时为每个对象类型生成interface/ 输入类型 / 可空包装MaybeT等结构保证编译期类型安全。而 javascript-client.ts 生成的则是运行时绑定从./prisma-schema读取 typeDefs通过makePrismaClientClass构造 Prisma 类并实例化use strict; Object.defineProperty(exports, __esModule, { value: true }); var prisma_lib_1 require(prisma-client-lib); var typeDefs require(./prisma-schema).typeDefs var models [...] exports.Prisma prisma_lib_1.makePrismaClientClass({...}); exports.prisma new exports.Prisma();makePrismaClientClass见 makePrismaClientClass.ts接收typeDefs、endpoint、secret、models四个参数返回一个继承自Client的类。而Client构造时见 Client.ts会用buildSchema(typeDefs)构建内部 schema若配置了secret用jsonwebtoken签发 tokensign({}, secret)并通过BatchedGraphQLClient为每个请求附加Authorization: Bearer token头创建订阅客户端SubscriptionClient把endpoint的http前缀替换为ws并配置inactivityTimeout: 60000、lazy: true、reconnect: true为$subscribe提供实时能力。正是这套实现让绑定函数即查询底层自动组装查询并发送从概念变成了可运行的代码。架构速览两层 GraphQL API使用 Prisma 构建 GraphQL 服务器时你实际面对的是两个 GraphQL API数据库层database layer由 Prisma 全权负责提供对数据库的 CRUD 与实时操作应用层application layer负责与数据库读写无直接关系的所有功能业务逻辑、认证与权限、第三方集成等。数据库层完全通过prisma.yml配置并用 Prisma CLI 管理应用层则是你用自己熟悉的编程语言实现的 GraphQL 服务器。更详细的架构剖析可参阅同一目录下的 03-Architecture.md。数据库层prisma.yml 与 datamodel.graphql每个 Prisma 服务从两个文件开始服务配置文件prisma.yml数据模型定义通常放在datamodel.graphql。能够生成上述博客示例所需 Prisma API 的最小prisma.yml如下# the name for the service # (will be part of the services HTTP endpoint) service: blogr # the cluster and stage the service is deployed to; # you can choose any string for that # (will be also part of the services HTTP endpoint) stage: dev # protects your Prisma API; # this is the value for the secret argument when # instantiating the Prisma binding instance secret: mysecret123 # the file path pointing to your data model datamodel: datamodel.graphql对应的datamodel.graphql可以是type Post { id: ID! unique title: String! published: Boolean! }注意尽管用了 SDL 语法这个文件并不是一个完整的 GraphQL schema它缺少定义 API 操作的根类型——datamodel.graphql只包含数据模型中的类型定义并作为生成 Prisma API 的基础。配置解析方面prisma-yml/src/PrismaDefinition.ts 展示了prisma.yml的加载细节load()会定位prisma.yml并读取定义支持通过--env-file结合dotenv注入环境变量secret字段会被replace(/\s/g, ).split(,)处理成密钥列表作为保护 Prisma API 的鉴权凭据。从 datamodel 到 Prisma API两份文件就绪后在包含它们的目录中运行prisma deploy即可部署 Prisma 服务。部署后你会得到一个为Post类型提供 CRUD 与实时操作的 Prisma API其生成的 GraphQL schema简化版如下type Query { posts(where: PostWhereInput, orderBy: PostOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Post]! post(where: PostWhereUniqueInput!): Post } type Mutation { createPost(data: PostCreateInput!): Post! updatePost(data: PostUpdateInput!, where: PostWhereUniqueInput!): Post deletePost(where: PostWhereUniqueInput!): Post } type Subscription { post(where: PostSubscriptionWhereInput): PostSubscriptionPayload } type Post implements Node { id: ID! title: String! published: Boolean }为简洁起见省略了Input与Payload类型。注意这个 Prisma API 与上面提到的application schema不同——它由数据模型自动生成字段上出现了PostWhereInput、PostOrderByInput、PostCreateInput等按需生成的输入类型以及分页参数skip、after、before、first、last这恰恰体现了 Prisma 帮你完成的重活把复杂的数据库访问能力自动生成成强类型、可组合的 GraphQL 层。应用层把 Prisma binding 注入 context应用层的典型装配方式以graphql-yoga为例应用 schema 存放在schema.graphqlresolver 实现如前述代码然后在创建GraphQLServer时通过context把Prismabinding 实例注入到每个 resolverconst server new GraphQLServer({ typeDefs: ./schema.graphql, // reference to the application schema resolvers, // the resolver implementations from above context: req ({ ...req, db: new Prisma({ typeDefs: prismaSchema, endpoint: prismaEndpoint, secret: prismaSecret, }), }), }) server.start()实例化GraphQLServer时可以为context设置初始值这里给它挂上db属性初始化为Prismabinding 实例。这个实例是 Prisma API 的接口它让 resolver 可以便捷地把传入查询转发给 Prisma——调用 binding 函数时底层会自动组装对应的 GraphQL 查询并通过 HTTP 发给 Prisma。于是应用层的每个 resolver 都只是转发数据库读写由 Prisma 完成这就是整个两层架构的核心闭环。实践要点总结从 schema 出发GraphQL 服务端开发的第一步永远是定义 schema根类型Query/Mutation/Subscription上的根字段构成 API 的全部入口点selection set 决定响应形状。Resolver 四参数parent上层返回值、args字段参数、context跨 resolver 共享、info查询 AST是每个 resolver 的固定签名。委托而非直连使用 Prisma 时 resolver 只做委托context.db.query.posts(...)这样的 binding 调用会由 Client.ts 自动组装查询、鉴权JWT Bearer token并发送订阅则通过 WebSocket 客户端实现。静态绑定提升体验在 TypeScript 等强类型语言中codegen/generators 会生成类型完整的绑定代码编译期即可捕获错误并享受自动补全JavaScript 场景则使用运行时动态绑定。两层 API 各司其职数据库层由prisma.ymldatamodel.graphql驱动、prisma deploy部署提供自动生成的 CRUD/实时 API应用层由你实现业务 schema 与 resolver通过 binding 把 Prisma API 的能力接入自己的服务端。赞分享后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载相关推荐基于 Prisma 构建 GraphQL Server从 Schema 定义、Resolver 实现到 GraphQL Bindings 的完整指南基于 Prisma 构建 GraphQL Server从 Schema 定义、Resolver 实现到 GraphQL Bindings 的完整指南 本篇技术后端数据库GraphQLPrisma 项目 GraphQL 服务端开发指南从 Schema 定义到 Resolver 委托与 GraphQL BindingPrisma 项目 GraphQL 服务端开发指南从 Schema 定义到 Resolver 委托与 GraphQL Binding 本篇技术指南聚焦 Pri后端数据库GraphQL基于 Prisma 与 Prisma Bindings 构建 GraphQL 服务端完整实战教程基于 Prisma 与 Prisma Bindings 构建 GraphQL 服务端完整实战教程 本教程面向已经拥有一个运行中的 Prisma 服务即至少已后端数据库GraphQL上一篇ToolJet Slack 数据源接入指南OAuth 授权、三种操作与源码级原理解析下一篇Label Studio 时间序列与视频/音频同步标注旧版 JS 注入方案实战与源码解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
从源码构建 Loop Habit Tracker(uhabits):Android Studio 与命令行两种完整方案 移动开发 【免费下载链接】uhabits Loop Habit Tracker, a mobile app for creating and maintaining long-term positive habits 项目地址: https://gitcode.com/gh_mirrors/uh/uhabits 点击查看 免费下载 导读
Loop Habit Tracker(仓库名 uhabits&am… · 2026/9/24 17:19:38
coss Command 组件全指南:用 Base UI 构建可键盘导航的命令面板 前端UI组件设计系统 【免费下载链接】coss coss.com/ui is the official design system of Cal.com 项目地址: https://gitcode.com/gh_mirrors/or/coss 点击查看 免费下载 coss 是 Cal.com 官方设计系统(位于本仓库 apps/ui 目录)ÿ… · 2026/9/24 17:19:38
Regal Linter 规则深度解析:pointless-import —— 用 Regal 消灭无效的自我导入 Regal Linter 规则深度解析:pointless-import —— 用 Regal 消灭无效的自我导入 【免费下载链接】opa Open Policy Agent (OPA) is an open source, general-purpose policy engine. 项目地址: https://gitcode.com/gh_mirrors/op/opa
Regal 是 Open Policy… · 2026/9/24 17:19:38
跨国SD-WAN服务商选型全解析:核心维度与实战避坑指南 在全球做业务的企业,网络是最让人头疼的底层问题之一。尤其是分公司分布在四五个国家,总部在国内或新加坡,业务系统部署在AWS、阿里云、Azure这种多云环境里,同时还要保证办公协同、视频会议、ERP等核心应用的访问体验,… · 2026/9/24 18:28:22
改进麻雀搜索算法原理与MATLAB实现:佳点集、黄金正弦与Levy飞行融合 我最早接触麻雀搜索算法(SSA)是在做一个配电网重构的课题里。当时的优化目标是非线性、多峰值、约束条件还特别多,标准SSA跑起来总是陷入局部最优,优化精度也马马虎虎。后来我试着把佳点集初始化、黄金正弦策略和Levy飞行策略三样… · 2026/9/24 18:28:16
Linux与Windows系统运维:参数查询与配置命令对照实战 很多时候,我们干的活儿并不是什么高深莫测的架构设计,反而是那些每天都在重复的“查一下参数、改一个配置”。尤其是当你的手头同时管着 Windows 服务器和 Linux 服务器时,这种“精神分裂”的感觉会特别明显:明明在 Windows 上用图… · 2026/9/24 18:28:09
RabbitMQ安装详解:Windows与Docker高频坑与权限排查 先聊点实际的。你点进这篇文章,多半是因为项目里突然要用消息队列,或者面试题刷到“RabbitMQ和Kafka怎么选”,又或者已经在Windows上装了RabbitMQ,结果服务死活起不来,管理界面也打不开。不管你是哪种情况,… · 2026/9/24 18:28:09
Linux与Windows参数查询与配置:双系统实战速查手册 1. 项目背景:为什么我要维护一份“Linux与Windows参数查询与配置”手册自从开始同时接触Linux服务器和Windows桌面环境,我就一直被同一个问题反复折磨:某个参数上次明明调通了,下次换台机器又得从头翻文档。更让人崩溃的是&#x… · 2026/9/24 18:28:09
Flutter状态边界:UI树才是决定setState刷新范围的关键 有人问我一个很经典的问题:setState明明调了,数据也变了,界面就是不动,到底哪里出了问题?我听完他的代码描述,第一反应不是去看状态管理库配没配好,而是反问他一句:你这段状态&#… · 2026/9/24 18:28:09
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44