如何在 SolidStart 中使用 Prisma ORM
介绍
Prisma ORM 通过类型安全的查询和流畅的开发体验简化了数据库访问。SolidStart 是一个使用 SolidJS 构建响应式 Web 应用程序的现代框架,它与 Prisma 和 Postgres 完美结合,可创建清晰且可扩展的全栈架构。
在本指南中,你将学习如何从头开始将 Prisma ORM 与 SolidStart 项目中的 Prisma Postgres 数据库集成。你可以在 GitHub 上找到本指南的完整示例。
先决条件
1. 设置项目
首先创建一个新的 SolidStart 应用程序。在你的终端中,运行
npm init solid@latest
出现提示时使用以下选项
- 项目名称:
my-solid-prisma-app - 这是 SolidStart 项目吗:
Yes - 模板:
bare - 使用 TypeScript:
Yes
接下来,导航到你的新项目,安装依赖项,并启动开发服务器
cd my-solid-prisma-app
npm install
npm run dev
开发服务器运行后,在浏览器中打开 https://:3000。你应该会看到 SolidStart 欢迎屏幕。
通过编辑 app.tsx 文件并将其内容替换为以下代码来清理默认 UI
import "./app.css";
export default function App() {
return (
<main>
<h1>SolidStart + Prisma</h1>
</main>
);
}
2. 安装和配置 Prisma
2.1. 安装依赖项
要开始使用 Prisma,您需要安装一些依赖项
npm install prisma tsx @types/pg --save-dev
npm install @prisma/client @prisma/adapter-pg dotenv pg
如果你使用的是其他数据库提供程序(MySQL、SQL Server、SQLite),请安装相应的驱动程序适配器包,而不是 @prisma/adapter-pg。有关更多信息,请参阅 数据库驱动程序。
安装后,在项目中初始化 Prisma
npx prisma init --db --output ../src/generated/prisma
在设置 Prisma Postgres 数据库时,你需要回答几个问题。选择离你位置最近的区域,并为你的数据库取一个好记的名字,例如“My SolidStart Project”
这将创建
- 一个包含
schema.prisma文件的prisma目录。 - 一个用于配置 Prisma 的
prisma.config.ts文件 - 一个 Prisma Postgres 数据库。
- 项目根目录中包含
DATABASE_URL的.env文件。 - 生成的 Prisma Client 的
output目录为src/generated/prisma。
2.2. 定义 Prisma Schema
在 prisma/schema.prisma 文件中,添加以下模型并更改生成器以使用 prisma-client 提供程序
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
}
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)
authorId Int
author User @relation(fields: [authorId], references: [id])
}
这将创建两个模型:User 和 Post,它们之间存在一对多关系。
2.3 将 dotenv 添加到 prisma.config.ts
要访问 .env 文件中的变量,它们可以由您的运行时加载,或者通过使用 dotenv 加载。在 prisma.config.ts 顶部包含 dotenv 的导入
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config';
export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
},
datasource: {
url: env('DATABASE_URL'),
},
});
2.4. 配置 Prisma Client 生成器
现在,运行以下命令创建数据库表并生成 Prisma Client
npx prisma migrate dev --name init
npx prisma generate
2.5. 填充数据库
让我们添加一些种子数据来用示例用户和帖子填充数据库。
在 prisma/ 目录中创建一个名为 seed.ts 的新文件
import { PrismaClient, Prisma } from "../src/generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg";
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL!,
});
const prisma = new PrismaClient({
adapter,
});
const userData: Prisma.UserCreateInput[] = [
{
name: "Alice",
email: "alice@prisma.io",
posts: {
create: [
{
title: "Join the Prisma Discord",
content: "https://pris.ly/discord",
published: true,
},
{
title: "Prisma on YouTube",
content: "https://pris.ly/youtube",
},
],
},
},
{
name: "Bob",
email: "bob@prisma.io",
posts: {
create: [
{
title: "Follow Prisma on Twitter",
content: "https://www.twitter.com/prisma",
published: true,
},
],
},
},
];
export async function main() {
for (const u of userData) {
await prisma.user.create({ data: u });
}
}
main();
现在,通过更新 prisma.config.ts 来告诉 Prisma 如何运行此脚本
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config';
export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
seed: `tsx prisma/seed.ts`,
},
datasource: {
url: env('DATABASE_URL'),
},
});
运行种子脚本
npx prisma db seed
并打开 Prisma Studio 检查您的数据
npx prisma studio
3. 将 Prisma 集成到 SolidStart
3.1. 创建 Prisma Client
在你的项目根目录中,创建一个新的 lib 文件夹并在其中创建一个 prisma.ts 文件
mkdir -p lib && touch lib/prisma.ts
添加以下代码以创建 Prisma Client 实例
import { PrismaClient } from "../src/generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg";
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL!,
});
const prisma = new PrismaClient({
adapter,
});
export default prisma;
我们建议使用连接池(如 Prisma Accelerate)来有效地管理数据库连接。
如果您选择不使用一个,请**避免**在长生命周期环境中全局实例化 PrismaClient。相反,请为每个请求创建和处置客户端,以防止耗尽数据库连接。
3.2. 创建一个 API 路由
现在,让我们使用 API 路由从数据库中获取数据。
在 src/routes/api/users.ts 创建一个新文件
import prisma from "../../../lib/prisma";
export async function GET() {
const users = await prisma.user.findMany({
include: {
posts: true,
},
});
return new Response(JSON.stringify(users), {
headers: { "Content-Type": "application/json" },
});
}
3.3. 在你的组件中获取数据
在你的 app.tsx 文件中,使用 createResource 从你的新 API 路由中获取数据
import "./app.css";
import { createResource } from "solid-js";
import { User, Post } from "./generated/prisma/client";
type UserWithPosts = User & {
posts: Post[];
};
const fetchUsers = async () => {
const res = await fetch("https://:3000/api/users");
return res.json();
};
export default function App() {
const [users, { mutate, refetch }] = createResource<UserWithPosts[]>(fetchUsers);
return (
<main>
<h1>SolidStart + Prisma</h1>
</main>
);
}
createResource 是 SolidJS 用于管理异步数据的 Hook。它会自动跟踪加载和错误状态。了解更多。
3.4. 显示数据
要显示用户及其帖子,请使用 SolidJS 的 <For> 组件
import "./app.css";
import { createResource, For } from "solid-js";
import { User, Post } from "./generated/prisma/client";
type UserWithPosts = User & {
posts: Post[];
};
const fetchUsers = async () => {
const res = await fetch("https://:3000/api/users");
return res.json();
};
export default function App() {
const [users, { mutate, refetch }] =
createResource<UserWithPosts[]>(fetchUsers);
return (
<main>
<h1>SolidJS + Prisma</h1>
<For each={users() ?? []}>
{(user) => (
<div>
<h3>{user.name}</h3>
<For each={user.posts}>{(post) => <p>{post.title}</p>}</For>
</div>
)}
</For>
</main>
);
}
<For> 响应式地遍历数组。将其视为 React 中的 .map()。了解更多
3.5. 添加加载和错误状态
使用 SolidJS 的 <Show> 组件来处理加载和错误情况
import "./app.css";
import { createResource, For, Show } from "solid-js";
import { User, Post } from "./generated/prisma/client";
type UserWithPosts = User & {
posts: Post[];
};
const fetchUsers = async () => {
const res = await fetch("https://:3000/api/users");
return res.json();
};
export default function App() {
const [users, { mutate, refetch }] =
createResource<UserWithPosts[]>(fetchUsers);
return (
<main>
<h1>SolidJS + Prisma</h1>
<Show when={!users.loading} fallback={<p>Loading...</p>}>
<Show when={!users.error} fallback={<p>Error loading data</p>}>
<For each={users()}>
{(user) => (
<div>
<h3>{user.name}</h3>
<For each={user.posts}>{(post) => <p>{post.title}</p>}</For>
</div>
)}
</For>
</Show>
</Show>
</main>
);
}
<Show> 有条件地渲染内容。它类似于 if 语句。了解更多
你完成了!你刚刚创建了一个连接到 Prisma Postgres 数据库的 SolidStart 应用程序。
下一步
现在你已经拥有一个连接到 Prisma Postgres 数据库的 SolidStart 应用程序,你可以
- 使用更多模型和关系扩展您的 Prisma schema
- 添加创建/更新/删除路由和表单
- 探索身份验证、验证和乐观更新
- 使用 Prisma Postgres 启用查询缓存以获得更好的性能
更多信息
与 Prisma 保持联系
通过以下方式与我们保持联系,继续你的 Prisma 之旅: 我们的活跃社区。保持信息灵通,参与其中,并与其他开发人员协作。
- 在 X 上关注我们 获取公告、直播活动和实用技巧。
- 加入我们的 Discord 提问、与社区交流,并通过对话获得积极支持。
- 在 YouTube 上订阅 获取教程、演示和直播。
- 在 GitHub 上参与 加星收藏存储库、报告问题或为问题做出贡献。