prisma-orm
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePrisma ORM Best Practices (2025-2026)
Prisma ORM 最佳实践(2025-2026版)
This skill provides guidelines and snippets for using Prisma ORM effectively in Shopify Apps built with Remix.
本指南提供了在基于Remix构建的Shopify应用中高效使用Prisma ORM的准则及代码片段。
1. Setup & Configuration
1. 安装与配置
Installation
安装步骤
bash
npm install prisma --save-dev
npm install @prisma/client
npx prisma initbash
npm install prisma --save-dev
npm install @prisma/client
npx prisma initRecommended schema.prisma
Config
schema.prisma推荐的schema.prisma
配置
schema.prismaUse the provider (standard for Shopify apps) or . Enable and other preview features if needed, but stick to stable for production.
postgresqlmysqlimproving-tracingprisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
// Useful features for 2025+
previewFeatures = ["driverAdapters", "metrics"]
}
// Standard Shopify Session Model
model Session {
id String @id
shop String
state String
isOnline Boolean @default(false)
scope String?
expires DateTime?
accessToken String
userId BigInt?
}使用驱动(Shopify应用的标准选择)或。若有需要可启用等预览功能,但生产环境请使用稳定特性。
postgresqlmysqlimproving-tracingprisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
// 2025+实用特性
previewFeatures = ["driverAdapters", "metrics"]
}
// 标准Shopify会话模型
model Session {
id String @id
shop String
state String
isOnline Boolean @default(false)
scope String?
expires DateTime?
accessToken String
userId BigInt?
}2. Singleton Pattern for Remix
2. Remix中的单例模式
In development, Remix reloads the server, which can exhaust database connections if you create a new on every reload. Use the singleton pattern.
PrismaClienttypescript
// app/db.server.ts
import { PrismaClient } from "@prisma/client";
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
export const prisma = globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;在开发环境中,Remix会重载服务器,若每次重载都创建新的会耗尽数据库连接。请使用单例模式。
PrismaClienttypescript
// app/db.server.ts
import { PrismaClient } from "@prisma/client";
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
export const prisma = globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;3. Schema Design Best Practices
3. Schema设计最佳实践
Use BigInt for Shopify IDs
为Shopify ID使用BigInt
Shopify IDs (Product ID, Order ID) exceed 32-bit integers.
- BAD:
Int - GOOD: (or
BigIntif you don't need math operations)String
prisma
model Product {
id BigInt @id // Matches Shopify's ID
shop String
title String
// ...
@@index([shop]) // Always index by shop for multi-tenancy
}Shopify的ID(如产品ID、订单ID)超出了32位整数范围。
- 不推荐:
Int - 推荐:(若无需数学运算也可使用
BigInt)String
prisma
model Product {
id BigInt @id // 匹配Shopify的ID格式
shop String
title String
// ...
@@index([shop]) // 多租户场景下务必按shop字段建立索引
}Multi-tenancy
多租户支持
Every query MUST filter by . This is non-negotiable for security.
shop- Tip: Use Prisma Middleware or Extensions to enforce this, or just be disciplined in your Service layer.
所有查询必须按字段过滤,这是安全性的硬性要求。
shop- 提示:可使用Prisma中间件或扩展来强制实现,或在服务层严格执行该规则。
4. Migrations Workflow
4. 迁移工作流
NEVER use in production.
prisma db push- Development:
bash
npx prisma migrate dev --name init_tables - Production (CI/CD):
bash
npx prisma migrate deploy
生产环境绝不要使用。
prisma db push- 开发环境:
bash
npx prisma migrate dev --name init_tables - 生产环境(CI/CD):
bash
npx prisma migrate deploy
5. Performance Optimization
5. 性能优化
Select Specific Fields
选择特定字段
Don't use without if you only need a few fields.
findManyselecttypescript
// BAD: Fetches massive JSON blobs
const products = await prisma.product.findMany();
// GOOD
const products = await prisma.product.findMany({
select: { id: true, title: true }
});若仅需部分字段,请勿在未指定的情况下使用。
selectfindManytypescript
// 不推荐:会获取大量JSON数据
const products = await prisma.product.findMany();
// 推荐
const products = await prisma.product.findMany({
select: { id: true, title: true }
});Transactions
事务处理
Use for dependent writes (e.g., creating an Order and its LineItems).
$transactiontypescript
await prisma.$transaction(async (tx) => {
const order = await tx.order.create({ ... });
await tx.lineItem.create({ ... });
});对于依赖型写入操作(如创建订单及其订单项),请使用。
$transactiontypescript
await prisma.$transaction(async (tx) => {
const order = await tx.order.create({ ... });
await tx.lineItem.create({ ... });
});Connection Pooling
连接池
For serverless or high-concurrency environments (like Remix on Vercel/Fly), use a connection pooler (Supabase Pooler, PgBouncer, or Prisma Accelerate).
对于无服务器或高并发环境(如部署在Vercel/Fly上的Remix应用),请使用连接池工具(如Supabase Pooler、PgBouncer或Prisma Accelerate)。
6. Common Recipes
6. 常用示例
Upsert (Create or Update)
Upsert(创建或更新)
Perfect for syncing data from Webhooks.
typescript
await prisma.user.upsert({
where: { id: 1 },
update: { email: "new@example.com" },
create: { id: 1, email: "new@example.com" },
});非常适用于从Webhook同步数据的场景。
typescript
await prisma.user.upsert({
where: { id: 1 },
update: { email: "new@example.com" },
create: { id: 1, email: "new@example.com" },
});