使用 Prisma 在 Next.js 中连接 MySQL 并查询数据

716 阅读4分钟

为什么选择 Prisma?

Prisma 不仅仅是一个 ORM,它还提供了以下显著的优势:

  • 类型安全:Prisma 生成的查询是类型安全的,避免了手写 SQL 时可能出现的类型错误。
  • 自动生成数据库模式:Prisma 会根据你的模型自动生成数据库的迁移文件,简化数据库结构的管理。
  • 简化数据库查询:相比手写 SQL,Prisma 的查询 API 更加直观且便于维护。
  • 现代开发体验:Prisma 与 TypeScript 集成良好,能够利用 TypeScript 的类型推断,极大提高开发效率。

环境准备

首先,在你的 Next.js 项目中安装 Prisma 相关的依赖:

pnpm add prisma @prisma/client

接下来,初始化 Prisma:

pnpm prisma init

这个命令将会在项目根目录下生成一个 prisma 目录和一个 .env 文件。在 .env 文件中,你可以配置 MySQL 数据库的连接字符串。

配置数据库连接

.env 文件中,找到 DATABASE_URL,并设置你的 MySQL 数据库连接信息:

DATABASE_URL="mysql://username:password@localhost:3306/database_name"

这里的 usernamepassword 替换为你 MySQL 的用户名和密码,database_name 则为你使用的数据库名称。

定义数据库模型

Prisma 使用 .prisma 文件来定义数据库模型。打开 prisma/schema.prisma,定义你的数据模型。例如,假设我们有一个用户表 User

// prisma/schema.prisma
datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

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

model User {
  id        Int      @id @default(autoincrement())
  name      String
  email     String   @unique
  createdAt DateTime @default(now())
}

在这个模型中,User 表拥有 idnameemailcreatedAt 字段。id 字段是自增的主键,email 字段是唯一的。

执行数据库迁移

在定义了模型后,我们需要将模型同步到数据库中。Prisma 提供了迁移工具,能够自动生成 SQL 并更新数据库结构。

执行以下命令生成并应用迁移:

pnpm prisma migrate dev --name init

这会自动在数据库中创建 User 表,并且生成相应的 SQL 文件。--name 参数是为这次迁移命名,便于管理多个数据库迁移。

生成 Prisma 客户端

在执行迁移之后,我们需要生成 Prisma 客户端,这个客户端将会在代码中被调用来与数据库交互:

pnpm prisma generate

Prisma 客户端是与数据库交互的桥梁,它根据你的数据库模型生成对应的查询方法,并确保类型安全。

查询数据

接下来,我们可以通过 Next.js 的 API 路由来查询数据库中的数据。在 pages/api/users.js 中,我们使用 Prisma 客户端来查询用户数据:

// pages/api/users.js
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export default async function handler(req, res) {
  try {
    const users = await prisma.user.findMany(); // 查询所有用户
    res.status(200).json(users);
  } catch (error) {
    console.error('Error fetching users:', error);
    res.status(500).json({ message: 'Internal Server Error' });
  } finally {
    await prisma.$disconnect(); // 断开数据库连接
  }
}

这里,我们使用了 prisma.user.findMany() 来查询所有用户。Prisma 的查询方法非常直观,findMany() 相当于 SQL 中的 SELECT * FROM。同时,Prisma 自动断开连接,保证性能和资源管理。

动态查询与过滤

Prisma 提供了丰富的查询 API,可以根据需求进行复杂的过滤查询。例如,如果我们想通过 id 参数来查询某个特定用户,可以这样写:

// pages/api/user.js
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export default async function handler(req, res) {
  const { id } = req.query;

  if (!id) {
    return res.status(400).json({ message: 'User ID is required' });
  }

  try {
    const user = await prisma.user.findUnique({
      where: { id: parseInt(id) } // 使用 ID 进行查询
    });

    if (!user) {
      return res.status(404).json({ message: 'User not found' });
    }

    res.status(200).json(user);
  } catch (error) {
    console.error('Error fetching user:', error);
    res.status(500).json({ message: 'Internal Server Error' });
  } finally {
    await prisma.$disconnect();
  }
}

在这个 API 路由中,prisma.user.findUnique() 用来查找唯一的用户记录,并且通过 where 子句指定查询条件(此处为 id)。Prisma 的查询 API 提供了强大的条件查询和类型检查,避免了手写 SQL 时可能出现的错误。

创建和更新数据

除了查询数据,Prisma 还可以非常方便地创建和更新数据库中的记录。以下是如何通过 API 创建一个新用户的例子:

// pages/api/createUser.js
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ message: 'Method not allowed' });
  }

  const { name, email } = req.body;

  try {
    const newUser = await prisma.user.create({
      data: { name, email }
    });
    res.status(201).json(newUser); // 返回新创建的用户
  } catch (error) {
    console.error('Error creating user:', error);
    res.status(500).json({ message: 'Internal Server Error' });
  } finally {
    await prisma.$disconnect();
  }
}

在这个 API 中,我们使用了 prisma.user.create() 方法来创建一条新记录。通过 req.body 提取客户端传来的 nameemail,然后插入数据库。

小结

通过 Prisma,Next.js 与 MySQL 的集成变得更加简洁和高效。它不仅简化了数据库操作,还提供了类型安全的查询方法,帮助开发者更快速、更可靠地编写后端逻辑。

  1. 易用性:Prisma 的直观 API 和自动生成的 TypeScript 类型极大简化了数据库操作。
  2. 灵活性:通过简单的查询方法,开发者可以执行复杂的查询、插入和更新操作。
  3. 高效开发:通过 Prisma 自动生成的客户端,开发者可以避免手写 SQL 提高开发效率,并且减少错误的可能性。