接下来为大家介绍使用 prisma + graphql 从0到1实现简单的查询、删除接口。
1. prisma
prisma官方介绍:下一代 Node.js、TypeScript、Go 的数据库 ORM;开源的数据库工具链项目,帮助开发人员更快地构建应用程序并减少错误,支持PostgreSQL、MySQL、MongoDB、SQL Server和SQLite。
可以以对象方式对数据库进行增删改查,十分方便,降低了数据库操作门槛。
参考www.prisma.io/docs/gettin...
安装
bash
mkdir hello-prisma
cd hello-prisma
npm init -y
npm install typescript ts-node @types/node --save-dev
# 生成 tsconfig.json文件
npx tsc --init
# 安装prisma
npm install prisma --save-dev
# 生成 prisma/schema.prisma 和 .env 文件,并指定使用的数据库为sqlite
npx prisma init --datasource-provider sqlite
出现如下提示说明命令执行成功
schema.prisma配置文件
schema.prisma 是 Primsa 的主要配置文件,它包含三个基本结构:数据源、生成器、数据模型定义。我们会在此文件中定义数据库的连接信息和模型。且可以用命令将此文件中的表结构同步至数据库,反之亦然。
这里方便起见,将prisma/schema.prisma中的url 地址改为本地文件./dev.db
ini
datasource db {
provider = "sqlite"
url = "file:./dev.db"
// url = env("DATABASE_URL")
}
在prisma/schema.prisma中添加与数据库表匹配的model: User、Post。
完整的prisma/schema.prisma 如下
kotlin
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schemagenerator
client {
provider = "prisma-client-js"
}
datasource db
{
provider = "sqlite"
url = "file:./dev.db"
// url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
与数据库同步
将表结构同步至数据库
perl
npx prisma db push
可以看出:同步之后,自动执行了prisma generate ,生成 了Prisma Client。Prisma Client可以用于执行 CRUD 操作。
如果Prisma Schema 文件发生了变动,比如修改、新增了模型,需要做两件事情:同步model至数据库、生成新Prisma Client。执行npx prisma db push 可以两件事情一步到位。
prisma提供了数据库GUI,执行 npx prisma studio 自动打开浏览器,可以看到刚刚创建的2个表。此时表内无数据。
向数据库添加一条记录
尝试创建一条user记录。创建script.ts 文件,并添加内容
javascript
// script.ts
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
//这段代码建议手写,以体验Prisma客户端提供的提示功能
// 以对象形式操作数据库,十分方便
const user = await prisma.user.create({
data: {
name: 'Alice',
// 按键盘上的CTRL+SPACE键,出现自动提示
email: 'alice@prisma.io',
},
})
console.log(user)
}
main()
.then(async () => {
await prisma.$disconnect()
})
.catch(async (e) => {
console.error(e)
await prisma.$disconnect()
process.exit(1)
})
执行script.ts文件
npx ts-node script.ts
查看GUI,可以看到数据库中生成了记录
可以看出,prisma作为ORM 工具,可以十分方便的实现简单的增删改查。
2. 安装graphql 及相关包
建议将TypeScript与GraphQL搭配一起使用,体验更好。这里使用type-script。
另外,typegraphql-prisma包提供了与prisma的typegraphql集成。 它基于Prisma模式生成类型类和CRUD解析器,可以则需使用。
安装graphql相关
参考typegraphql.com/docs/instal...
matlab
npm install type-graphql@2.0.0-beta.1
npm install graphql graphql-scalars
npm install reflect-metadatat
在script.ts文件顶部import
arduino
import "reflect-metadata";
安装typegraphql-prisma相关
参考prisma.typegraphql.com/docs/basics...
css
npm i -D typegraphql-prisma
npm i graphql-scalars
npm i graphql-fields @types/graphql-fields
npm i tslib
prisma 添加generator typegraphql 相关内容
ini
generator typegraphql {
provider = "typegraphql-prisma"
}
执行命令
npx prisma generate
查看/node_modules/@generated/type-graphql,可以发现生成的ts类型文件。可以择需使用。
安装@apollo/server
graphql 的 npm 包,封装的不够好,一般我们会用基于 graphql 包的 @apollo/server 和 @apollo/client 的包来实现 graphql
bash
npm install @apollo/server
实现查询功能
新建resolvers/user.resolvers.ts文件,这里先实现简单的查询功能
typescript
import { Query, Resolver } from 'type-graphql';
import { User} from '@generated/type-graphql';
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient();
@Resolver(User)
export class UserResolver {
@Query(() => [User])
async users() {
return await prisma.user.findMany();
}
}
tsconfig.json文件内配置改为如下
json
{
"compilerOptions": {
"target": "es2021",
"module": "commonjs",
"lib": ["es2018", "esnext.asynciterable"],
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
script.ts 修改为使用@apollo/server,内容如下
javascript
import "reflect-metadata";
import { buildSchema } from 'type-graphql';
import { UserResolver } from './resolvers/user.resolvers';
import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
async function bootstrap() {
const schema = await buildSchema({
resolvers: [
UserResolver
],
});
const server = new ApolloServer({ schema });
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 }
});
console.log(`GraphQL server ready at ${url}`);
}
bootstrap();
执行npx ts-node script.ts,打开浏览器,操作刚刚的编写的查询接口
实现删除功能
typescript
export class UserResolver {
@Query(() => [User])
async users() {
return await prisma.user.findMany();
}
@Mutation(() => User, { description: '删除' })
async UserDelete(
@Arg('id') id: number,
): Promise<User> {
const user = await prisma.user.delete({
where: {
id
}
})
return user;
}}
之前的例子中,PrismaClient 是在resolver文件中声明。更合适的做法是在外部声明,这样任意resolver文件都可以饮用。这里可以使用context。
修改script.ts 文件如下:
javascript
import "reflect-metadata";
import { buildSchema } from 'type-graphql';
import { UserResolver } from './resolvers/user.resolvers';
import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
import { PrismaClient } from '@prisma/client'const prisma = new PrismaClient();
export interface Context {
prisma: PrismaClient;
}
async function bootstrap() {
const schema = await buildSchema({
resolvers: [
UserResolver
],
});
const server = new ApolloServer({ schema });
const { url } = await startStandaloneServer(server, {
context: async () => ({ prisma }),
listen: { port: 4000 }
});
console.log(`GraphQL server ready at ${url}`);
}
bootstrap();
修改resolvers/user.resolvers.ts文件如下
less
import { Mutation, Arg, Query, Resolver, Ctx } from 'type-graphql';
import {
User
} from '@generated/type-graphql';
import { Context } from '../script';
@Resolver(User)
export class UserResolver {
@Query(() => [User])
async users(
@Ctx() { prisma }: Context
) {
return await prisma.user.findMany();
}
@Mutation(() => User, { description: '删除' })
async UserDelete(
@Arg('id') id: number,
@Ctx() { prisma }: Context
): Promise<User> {
const user = await prisma.user.delete({
where: {
id
}
})
return user;
}}