跳至主要內容

如何使用 Prisma ORM 搭配 SolidStart

10 分鐘

簡介

Prisma ORM 透過型別安全(type-safe)的查詢和流暢的開發者體驗,簡化了資料庫存取。SolidStart 是一個用於構建響應式 Web 應用的現代化 SolidJS 框架,它與 Prisma 和 Postgres 搭配使用,能夠建立整潔且可擴展的全端架構。

在本指南中,您將學習如何從零開始在 SolidStart 專案中整合 Prisma ORM 與 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:

src/app.tsx
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 檔案中,加入下列模型並將 generator 修改為使用 prisma-client 提供者

prisma/schema.prisma
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])
}

這會建立兩個模型:UserPost,且兩者之間具有一對多關係。

2.3 在 prisma.config.ts 加入 dotenv

要存取 .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. 進行資料庫植入 (Seed)

讓我們加入一些種子資料,以在資料庫中填充範例使用者與貼文。

prisma/ 目錄中建立一個名為 seed.ts 的新檔案

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 如何執行此指令碼

prisma.config.ts
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 實例:

lib/prisma.ts
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 建立一個新檔案:

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 路由獲取資料:

src/app.tsx
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> 組件:

src/app.tsx
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> 組件來處理載入與錯誤條件:

src/app.tsx
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
  • 加入建立/更新/刪除 (CRUD) 的路由與表單
  • 探索身分驗證(Authentication)、驗證(Validation)以及樂觀更新(Optimistic Updates)
  • 啟用 Prisma Postgres 的查詢快取以獲得更好的效能

更多資訊


與 Prisma 保持聯繫

透過以下方式與我們聯繫,繼續您的 Prisma 旅程: 我們的活躍社群。保持資訊靈通、參與其中,並與其他開發者合作

我們衷心感謝您的參與,並期待您成為我們社群的一份子!

© . This site is unofficial and not affiliated with Prisma Data, Inc.