Skip to content
On this page

Prisma 快速入门

Prisma是现代数据库工具包,它提供了类型安全的数据库访问和直观的数据建模。Prisma ORM通过其类型安全的查询API、自动迁移和直观的数据建模语言,简化了数据库操作。

什么是Prisma

Prisma是一个现代化的数据库工具包,包含以下组件:

  • Prisma Client:类型安全的数据库客户端
  • Prisma Migrate:数据库迁移系统
  • Prisma Studio:数据库GUI工具
  • Prisma Schema:数据建模语言

主要特性

  • 类型安全:完全类型安全的数据库查询
  • 直观API:简洁易用的查询API
  • 数据建模:直观的模式定义语言
  • 自动迁移:安全的数据库迁移
  • 数据库支持:支持PostgreSQL、MySQL、SQLite、SQL Server、MongoDB

安装Prisma

初始化项目

bash
# 创建新项目
mkdir my-prisma-project
cd my-prisma-project
npm init -y

# 安装Prisma作为开发依赖
npm install prisma --save-dev

# 安装Prisma Client
npm install @prisma/client

初始化Prisma

bash
# 初始化Prisma(创建schema文件和node_modules/.prisma目录)
npx prisma init

这将创建以下文件:

  • prisma/schema.prisma:Prisma模式文件
  • .env:环境变量文件(包含数据库连接URL)

配置数据库连接

数据库连接配置

编辑生成的.env文件:

text
# PostgreSQL
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"

# MySQL
DATABASE_URL="mysql://user:password@localhost:3306/mydb"

# SQLite
DATABASE_URL="file:./dev.db"

# SQL Server
DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=user;password=password;"

# MongoDB (实验性)
DATABASE_URL="mongodb+srv://user:password@cluster.mongodb.net/mydb"

配置Prisma Schema

编辑prisma/schema.prisma文件:

prisma
// prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"  // 或 "mysql", "sqlite", "sqlserver", "mongodb"
  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
}

安装数据库驱动

根据使用的数据库安装相应的驱动:

bash
# PostgreSQL
npm install pg

# MySQL
npm install mysql2

# SQLite
npm install sqlite3

# SQL Server
npm install tedious

# MongoDB (实验性)
npm install @prisma/adapter-mongodb

数据库迁移

创建和应用迁移

bash
# 创建并应用迁移
npx prisma migrate dev --name init

# 或者使用别名
npx prisma migrate dev

生成迁移文件

这将创建一个迁移文件,例如:

prisma/migrations/
└── 20231201235959_init/
    └── migration.sql

在应用中使用Prisma Client

基本设置

javascript
// app.js
const { PrismaClient } = require('@prisma/client')
const prisma = new PrismaClient()

async function main() {
  // 创建用户
  const user = await prisma.user.create({
    data: {
      name: 'Alice',
      email: 'alice@prisma.io',
    },
  })
  console.log(user)

  // 创建帖子
  const post = await prisma.post.create({
    data: {
      title: 'Hello Prisma',
      content: 'This is my first post',
      author: {
        connect: { email: 'alice@prisma.io' },
      },
    },
  })
  console.log(post)
}

main()
  .then(async () => {
    await prisma.$disconnect()
  })
  .catch(async (e) => {
    console.error(e)
    await prisma.$disconnect()
    process.exit(1)
  })

使用ES6模块

javascript
// app.mjs
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

async function main() {
  // 查询所有用户
  const allUsers = await prisma.user.findMany()
  console.log(allUsers)

  // 查询特定用户及其帖子
  const userWithPosts = await prisma.user.findUnique({
    where: { email: 'alice@prisma.io' },
    include: { posts: true },
  })
  console.log(userWithPosts)
}

main()
  .finally(async () => {
    await prisma.$disconnect()
  })

基本CRUD操作

创建数据

javascript
// 创建单个记录
const user = await prisma.user.create({
  data: {
    name: 'John Doe',
    email: 'john@example.com',
  },
})

// 创建多个记录
const users = await prisma.user.createMany({
  data: [
    { name: 'User 1', email: 'user1@example.com' },
    { name: 'User 2', email: 'user2@example.com' },
  ],
})

读取数据

javascript
// 查询单个记录
const user = await prisma.user.findUnique({
  where: { email: 'john@example.com' },
})

// 查询多个记录
const users = await prisma.user.findMany({
  where: {
    name: { contains: 'John' },
  },
  take: 10, // 限制结果数量
  orderBy: { name: 'asc' }, // 排序
})

// 计数
const userCount = await prisma.user.count({
  where: { email: { endsWith: '@example.com' } },
})

更新数据

javascript
// 更新单个记录
const updatedUser = await prisma.user.update({
  where: { email: 'john@example.com' },
  data: { name: 'John Smith' },
})

// 更新多个记录
const updatedUsers = await prisma.user.updateMany({
  where: { name: { contains: 'Smith' } },
  data: { name: { set: 'Updated Name' } },
})

// 条件更新
const result = await prisma.user.updateMany({
  where: { email: { endsWith: '@old-domain.com' } },
  data: {
    email: { 
      // 在实际应用中,这需要更复杂的逻辑来更新邮箱
    }
  },
})

删除数据

javascript
// 删除单个记录
const deletedUser = await prisma.user.delete({
  where: { email: 'john@example.com' },
})

// 删除多个记录
const deletedCount = await prisma.user.deleteMany({
  where: { name: { contains: 'Spam' } },
})

关系查询

包含关联数据

javascript
// 获取用户及其所有帖子
const userWithPosts = await prisma.user.findUnique({
  where: { id: 1 },
  include: {
    posts: true,
  },
})

// 获取帖子及其作者
const postWithAuthor = await prisma.post.findUnique({
  where: { id: 1 },
  include: {
    author: true,
  },
})

// 嵌套包含
const userWithPostsAndComments = await prisma.user.findUnique({
  where: { id: 1 },
  include: {
    posts: {
      include: {
        comments: true,
      },
    },
  },
})

过滤关联数据

javascript
// 获取有特定帖子的用户
const usersWithPublishedPosts = await prisma.user.findMany({
  where: {
    posts: {
      some: {
        published: true,
      },
    },
  },
  include: {
    posts: {
      where: {
        published: true,
      },
    },
  },
})

Prisma Studio

Prisma Studio是一个数据库GUI工具,用于查看和编辑数据库中的数据。

bash
# 启动Prisma Studio
npx prisma studio

这将在浏览器中打开http://localhost:5555,您可以在其中查看和编辑数据库数据。

数据模型定义

基本字段类型

prisma
model User {
  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  email     String   @unique
  name      String?
  isAdmin   Boolean  @default(false)
  age       Int?
  height    Float?
  role      Role     @default(USER)
  permissions String[]
}

enum Role {
  USER
  ADMIN
  MODERATOR
}

关系定义

prisma
model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  
  // 一对多关系
  posts Post[]
  
  // 一对一关系
  profile Profile?
}

model Profile {
  id     Int   @id @default(autoincrement())
  bio    String?
  user   User  @relation(fields: [userId], references: [id])
  userId Int   @unique
}

model Post {
  id        Int    @id @default(autoincrement())
  title     String
  content   String?
  published Boolean @default(false)
  author    User    @relation(fields: [authorId], references: [id])
  authorId  Int
}

高级查询

连接查询

javascript
// 使用where条件查询
const posts = await prisma.post.findMany({
  where: {
    AND: [
      { title: { contains: 'Prisma' } },
      { published: true },
      { author: { email: { endsWith: '@prisma.io' } } },
    ],
  },
  include: {
    author: {
      select: {
        name: true,
        email: true,
      },
    },
  },
})

// 聚合查询
const result = await prisma.post.aggregate({
  where: { published: true },
  _count: true,
  _avg: { authorId: true },
  _sum: { id: true },
})

原生SQL查询

javascript
// 原生SQL查询(仅适用于SQL数据库)
const posts = await prisma.$queryRaw`SELECT * FROM Post WHERE title LIKE ${'%Prisma%'}`

// 原生SQL执行
const result = await prisma.$executeRaw`UPDATE Post SET published = true WHERE id = ${postId}`

连接池配置

javascript
// 自定义Prisma Client配置
const { PrismaClient } = require('@prisma/client')

const prisma = new PrismaClient({
  log: ['query', 'info', 'warn', 'error'], // 启用查询日志
  datasourceUrl: process.env.DATABASE_URL,
})

// 或者使用更详细的配置
const prisma = new PrismaClient({
  datasources: {
    db: {
      url: process.env.DATABASE_URL,
    },
  },
  log: [
    { level: 'query', emit: 'event' },  // 记录所有查询
    { level: 'info', emit: 'stdout' },
    { level: 'warn', emit: 'stdout' },
    { level: 'error', emit: 'stdout' },
  ],
})

// 监听查询事件
prisma.$on('query', (e) => {
  console.log('Query: ' + e.query)
  console.log('Params: ' + e.params)
  console.log('Duration: ' + e.duration + 'ms')
})

完整示例应用

javascript
// server.js - Express + Prisma示例
const express = require('express')
const { PrismaClient } = require('@prisma/client')

const prisma = new PrismaClient()
const app = express()

app.use(express.json())

// 创建用户
app.post('/users', async (req, res) => {
  const { name, email } = req.body
  const user = await prisma.user.create({
    data: {
      name,
      email,
    },
  })
  res.json(user)
})

// 获取所有用户
app.get('/users', async (req, res) => {
  const users = await prisma.user.findMany()
  res.json(users)
})

// 获取特定用户
app.get('/users/:id', async (req, res) => {
  const { id } = req.params
  const user = await prisma.user.findUnique({
    where: { id: Number(id) },
    include: { posts: true },
  })
  res.json(user)
})

// 创建帖子
app.post('/posts', async (req, res) => {
  const { title, content, authorEmail } = req.body
  const post = await prisma.post.create({
    data: {
      title,
      content,
      author: {
        connect: { email: authorEmail },
      },
    },
  })
  res.json(post)
})

// 启动服务器
const server = app.listen(3000, async () => {
  console.log('Server started on http://localhost:3000')
  console.log('Prisma is connected to the database')
})

// 优雅关闭
process.on('SIGINT', async () => {
  console.log('\nShutting down gracefully...')
  await prisma.$disconnect()
  server.close(() => {
    console.log('Server closed')
    process.exit(0)
  })
})

常用命令

bash
# 生成Prisma Client(在模式更改后)
npx prisma generate

# 检查模式
npx prisma db pull

# 推送模式到数据库(非生产环境)
npx prisma db push

# 部署迁移到生产数据库
npx prisma migrate deploy

# 验证模式
npx prisma validate

# 格式化模式文件
npx prisma format

总结

Prisma提供了一个现代化的数据库访问解决方案,具有类型安全、直观API和强大的功能。通过本章的学习,你应该已经掌握了Prisma的基本概念和使用方法。在接下来的章节中,我们将深入探讨Prisma的高级特性和最佳实践。