跳到主要内容

如何在单个应用程序中使用多个数据库

15 分钟

简介

本指南将向你展示如何在单个 Next.js 应用程序 中使用 Prisma ORM 连接多个数据库。你将学习如何连接两个不同的 Prisma Postgres 数据库、管理迁移并将应用程序部署到 Vercel。此方法适用于多租户应用程序,或在管理多个数据库连接时需要分离关注点的情况。

先决条件

在开始之前,请确保你已具备以下条件:

  • 已安装 Node.js 18+。
  • 一个 Prisma 数据平台账户
  • 一个 Vercel 账户(如果你计划部署你的应用程序)。

1. 设置 Next.js 项目

在你想要的目录下使用 create-next-app 创建一个新的 Next.js 应用程序

npx create-next-app@latest my-multi-client-app

系统将提示你回答有关项目的一些问题。选择所有默认选项。

信息

为完整起见,这些选项是:

  • TypeScript
  • ESLint
  • Tailwind CSS
  • src 目录
  • App Router
  • Turbopack
  • 默认自定义导入别名:@/*

然后,导航到项目目录

cd my-multi-client-app

2. 设置数据库和 Prisma Client

在本节中,你将创建两个独立的 Prisma Postgres 实例——一个用于用户数据,一个用于帖子数据。你还将为每个实例配置 Prisma schema 和环境变量。

首先,安装 Prisma 作为开发依赖项

npm install -D prisma

安装使用 Prisma Postgres 所需的 Prisma Client 扩展

npm install @prisma/extension-accelerate
信息

如果你不使用 Prisma Postgres 数据库,则不需要 @prisma/extension-accelerate 包。

你已安装项目所需的依赖项。

2.1. 创建包含用户数据的 Prisma Postgres 实例

通过运行以下命令使用 Prisma Postgres 实例初始化 Prisma

npx prisma@latest init --db
信息

如果你不使用 Prisma Postgres 数据库,请勿使用 --db 标志。相反,请创建两个 PostgreSQL 数据库实例,并将其连接 URL 添加到 .env 文件中,分别命名为 PPG_USER_DATABASE_URLPPG_POST_DATABASE_URL

按照提示为你的项目命名并选择数据库区域。

prisma@latest init --db 命令会:

  • 将你的 CLI 连接到你的账户。如果你未登录或没有账户,浏览器将打开,引导你创建新账户或登录现有账户。
  • 创建一个包含数据库模型 schema.prisma 文件的 prisma 目录。
  • 创建一个包含你的 DATABASE_URL.env 文件(例如,对于 Prisma Postgres,它应该类似于 DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI...")。

prisma 文件夹重命名为 prisma-user-database

mv prisma prisma-user-database

编辑你的 .env 文件,将 DATABASE_URL 重命名为 PPG_USER_DATABASE_URL

.env
DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI...
PPG_USER_DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI...

打开 prisma-user-database/schema.prisma 文件并更新它以定义 User 模型。此外,设置环境变量并为生成的 Prisma Client 指定一个 自定义 output 目录

prisma-user-database/schema.prisma
generator client {
provider = "prisma-client-js"
output = "../prisma-user-database/user-database-client-types"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
url = env("PPG_USER_DATABASE_URL")
}

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}

你的用户数据库模式现已准备就绪。

2.2. 创建用于帖子数据的 Prisma Postgres 实例

重复帖子的数据库初始化

npx prisma init --db

按照提示操作后,将新的 prisma 文件夹重命名为 prisma-post-database

mv prisma prisma-post-database

.env 中的 DATABASE_URL 变量重命名为 PPG_POST_DATABASE_URL

.env
DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI...
PPG_POST_DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI...

编辑 prisma-post-database/schema.prisma 文件以定义 Post 模型。此外,更新数据源 URL 并设置一个 自定义 output 目录

prisma-post-database/schema.prisma
generator client {
provider = "prisma-client-js"
output = "../prisma-post-database/post-database-client-types"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
url = env("PPG_POST_DATABASE_URL")
}

model Post {
id Int @id @default(autoincrement())
title String
content String?
}

你的帖子数据库模式现已设置完毕。

2.3. 添加辅助脚本并迁移模式

为简化你的工作流程,请在 package.json 文件中添加辅助脚本,用于运行两个数据库的 Prisma 命令

package.json
"script":{
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint",
"postinstall": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine",
"generate": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine",
"migrate": "npx prisma migrate dev --schema ./prisma-user-database/schema.prisma && npx prisma migrate dev --schema ./prisma-post-database/schema.prisma",
"deploy": "npx prisma migrate deploy --schema ./prisma-user-database/schema.prisma && npx prisma migrate deploy --schema ./prisma-post-database/schema.prisma",
"studio": "npx prisma studio --schema ./prisma-user-database/schema.prisma --port 5555 & npx prisma studio --schema ./prisma-post-database/schema.prisma --port 5556"
}
信息

如果你不使用 Prisma Postgres 数据库,请从上述自定义脚本中移除 --no-engine 标志。

以下是自定义脚本的说明:

  • postinstall:在安装依赖项后立即运行,使用各自的模式文件为用户数据库和帖子数据库生成 Prisma Clients。
  • generate:手动触发两个模式的 Prisma Clients 生成,确保你的客户端代码反映最新的模型。
  • migrate:使用 Prisma Migrate 在开发模式下为两个数据库应用待处理的迁移,根据 Prisma 文件中的更改更新它们的模式。
  • deploy:在生产环境中执行迁移,将你的实时数据库与你的 Prisma 模式同步。
  • studio:同时为两个数据库在不同端口(用户数据库为 5555,帖子数据库为 5556)打开 Prisma Studio,以便进行可视化数据管理。

运行迁移

npm run migrate

当系统提示时,为每个数据库相应地命名迁移。

3. 准备应用程序以使用多个 Prisma Client

接下来,创建一个 lib 文件夹,用于存储实例化和导出你的 Prisma Client 的辅助文件

mkdir -p lib && touch lib/user-prisma-client.ts lib/post-prisma-client.ts

3.1. 实例化并导出用户数据库的 Prisma Client

lib/user-prisma-client.ts 中,添加以下代码

lib/user-prisma-client.ts
import { PrismaClient } from "../prisma-user-database/user-database-client-types";
import { withAccelerate } from "@prisma/extension-accelerate"

const getPrisma = () => new PrismaClient().$extends(withAccelerate());

const globalForUserDBPrismaClient = global as unknown as {
userDBPrismaClient: ReturnType<typeof getPrisma>;
};

export const userDBPrismaClient =
globalForUserDBPrismaClient.userDBPrismaClient || getPrisma();

if (process.env.NODE_ENV !== "production")
globalForUserDBPrismaClient.userDBPrismaClient = userDBPrismaClient;
信息

如果你不使用 Prisma Postgres 数据库,请勿使用 withAccelerate 客户端扩展来扩展 PrismaClient

3.2. 实例化并导出帖子数据库的 Prisma Client

lib/post-prisma-client.ts 中,添加以下代码

lib/post-prisma-client.ts
import { PrismaClient } from "../prisma-post-database/post-database-client-types";
import { withAccelerate } from "@prisma/extension-accelerate"

const getPrisma = () => new PrismaClient().$extends(withAccelerate());

const globalForPostDBPrismaClient = global as unknown as {
postDBPrismaClient: ReturnType<typeof getPrisma>;
};

export const postDBPrismaClient =
globalForPostDBPrismaClient.postDBPrismaClient || getPrisma();

if (process.env.NODE_ENV !== "production")
globalForPostDBPrismaClient.postDBPrismaClient = postDBPrismaClient;
信息

如果你不使用 Prisma Postgres 数据库,请勿使用 withAccelerate 客户端扩展来扩展 PrismaClient

4. 在 Next.js 应用中集成多个 Prisma Client

修改你的应用程序代码以从两个数据库中获取数据。如下更新 app/page.tsx 文件

app/page.tsx
import { postDBPrismaClient } from "@/lib/post-prisma-client";
import { userDBPrismaClient } from "@/lib/user-prisma-client";

export default async function Home() {
const user = await userDBPrismaClient.user.findFirst();
const post = await postDBPrismaClient.post.findFirst();

return (
<main className="min-h-screen bg-gray-50 py-12">
<div className="max-w-4xl mx-auto px-4">
<header className="mb-12 text-center">
<h1 className="text-5xl font-extrabold text-gray-900">Multi-DB Showcase</h1>
<p className="mt-4 text-xl text-gray-600">
Data fetched from two distinct databases.
</p>
</header>

<section className="mb-8 bg-white shadow-md rounded-lg p-6">
<h2 className="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">
User Data
</h2>
<pre className="whitespace-pre-wrap text-sm text-gray-700">
{user ? JSON.stringify(user, null, 2) : "No user data available."}
</pre>
</section>

<section className="bg-white shadow-md rounded-lg p-6">
<h2 className="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4">
Post Data
</h2>
<pre className="whitespace-pre-wrap text-sm text-gray-700">
{post ? JSON.stringify(post, null, 2) : "No post data available."}
</pre>
</section>
</div>
</main>
);
}

4.1. 使用数据填充你的数据库

在一个单独的终端窗口中,打开两个 Prisma Studio 实例,通过运行脚本向数据库添加数据

npm run studio

这将打开两个浏览器窗口,一个在 http://localhost:5555,另一个在 http://localhost:5556。导航到这些窗口并向两个数据库添加示例数据。

4.2. 运行开发服务器

在启动开发服务器之前,请注意,如果你使用的是 Next.js v15.2.0,请勿使用 Turbopack,因为存在一个已知的 问题。通过更新 package.json,从你的开发脚本中移除 Turbopack

package.json
"script":{
"dev": "next dev --turbopack",
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"postinstall": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine",
"generate": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine",
"migrate": "npx prisma migrate dev --schema ./prisma-user-database/schema.prisma && npx prisma migrate dev --schema ./prisma-post-database/schema.prisma",
"deploy": "npx prisma migrate deploy --schema ./prisma-user-database/schema.prisma && npx prisma migrate deploy --schema ./prisma-post-database/schema.prisma",
"studio": "npx prisma studio --schema ./prisma-user-database/schema.prisma --port 5555 & npx prisma studio --schema ./prisma-post-database/schema.prisma --port 5556"
}

在一个单独的终端窗口中,通过运行以下命令启动开发服务器

npm run dev

导航到 http://localhost:3000,查看你的 Next.js 应用程序显示来自两个数据库的数据

App displaying data by querying two separate database instances

恭喜你,你的 Next.js 应用程序已成功运行,并使用两个 Prisma Client 实例查询不同的数据库。

5. 使用多个数据库将 Next.js 应用程序部署到 Vercel

按照以下步骤部署你的应用程序

  1. 确保你的项目已进行版本控制并推送到 GitHub 仓库。如果你还没有仓库,请在 GitHub 上创建一个。仓库准备就绪后,运行以下命令:
    git add .
    git commit -m "Initial commit with Prisma Postgres integration"
    git branch -M main
    git remote add origin https://github.com/<your-username>/<repository-name>.git
    git push -u origin main
    注意

    <your-username><repository-name> 替换为你的 GitHub 用户名和仓库名称。

  2. 登录 Vercel 并导航到你的仪表盘
  3. 创建一个新项目。按照 Vercel 的 导入现有项目 指南操作,但在单击部署之前,请在 步骤 3 处配置环境变量。
  4. 配置 DATABASE_URL 环境变量
    1. 展开环境变量部分。
    2. 添加 PPG_USER_DATABASE_URL 环境变量
      • PPG_USER_DATABASE_URL
      • :粘贴你的用户数据库连接 URL,例如,从你项目中的 .env 文件复制。
    3. 添加 PPG_POST_DATABASE_URL 环境变量
      • PPG_POST_DATABASE_URL
      • :粘贴你的帖子数据库连接 URL,例如,从你项目中的 .env 文件复制。
    警告

    未设置环境变量请勿部署。如果应用程序无法连接到数据库,你的部署将失败。

  5. 单击部署按钮。Vercel 将构建你的项目并将其部署到实时 URL。

打开 Vercel 提供的实时 URL 并验证你的应用程序是否正常工作。

恭喜!你已成功部署了一个使用多个 Prisma Client 查询两个不同数据库的应用程序,它现在已在 Vercel 上线并全面运行。

后续步骤

在本指南中,你学习了如何在单个 Next.js 应用程序中使用 Prisma ORM 来操作多个数据库,具体方法包括:

  • 为用户和帖子数据库设置独立的 Prisma 模式。
  • 配置自定义输出目录和环境变量。
  • 创建辅助脚本来生成和迁移每个模式。
  • 实例化多个 Prisma Client 并将其集成到你的应用程序中。
  • 将你的多数据库应用程序部署到 Vercel。

这种方法可以让你保持数据模型的清晰分离,并简化多租户或多数据库场景。

为了进一步改进项目管理,请考虑使用 monorepo 设置。查看我们的相关指南:


与 Prisma 保持联系

通过以下方式与我们联系,继续你的 Prisma 之旅: 我们活跃的社区。保持信息更新,参与其中,并与其他开发者协作

我们真诚地重视你的参与,并期待你成为我们社区的一员!

© . All rights reserved.