首页 / 文章 / 实用指南:Drizzle与Prisma——2026年如何选择合适的TypeScript ORM

实用指南:Drizzle与Prisma——2026年如何选择合适的TypeScript ORM

《实用笔记》操作指南:Drizzle与Prisma——2026年如何选择合适的TypeScript ORM:适用于采用该架构的团队的契约、校验机制及可直接插入的代码模块。

2401 词

本指南将逐步构建从原始材料到可运行系统的完整流程,主题为《Drizzle与Prisma:2026年选择合适的TypeScript ORM(深度解析)》。重点在于可操作的步骤、明确的检查点,以及可直接放入代码库而无需猜测其用途的代码。 在概览阶段,应在修改代码之前明确输入参数、各步骤的负责人以及完成标准。操作人员应能够从已知的检查点重新运行相应步骤,而无需猜测其中的隐藏状态。 配置信息应与应用程序代码分开存放。环境文件、密钥存储以及功能开关都应集中管理,这样操作人员只需查看这些特定内容即可,无需浏览整个系统结构。

Drizzle ORM

在处理 Drizzle ORM 阶段时,首先需明确相关约定:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 同时记录正常流程与异常恢复流程。重试机制、人工审核环节以及死信处理都是产品功能的一部分,而非后续需要补充的内容。 编写一份简短的操作手册:说明如何轮换密钥、如何清空队列,以及如何回滚上一次的数据导入操作。

Prisma

在处理 Prisma 阶段时,首先需写下契约内容:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 建议使用小型、可测试的单元而非庞大的脚本。当某个步骤失败时,故障应指向单一的责任模块,而非复杂的流程链。 编写简短的操作手册:说明如何轮换密钥、如何清空队列,以及如何回滚上一次的数据导入操作。

模式定义

在处理架构定义阶段时,首先需明确相关约定:所需的输入参数、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改始终符合约定。 将此阶段视为输入与验证后输出之间的契约。为相关组件命名,定义成功检测标准,并杜绝无声的半完成状态。 编写简短的操作手册:说明如何轮换密钥、如何清空队列、以及如何回滚上一次的数据导入操作。 在处理架构定义阶段时,首先需明确相关约定:所需的输入参数、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改始终符合约定。 将配置信息与应用程序代码分开存放。环境文件、密钥存储以及功能开关应集中于一处,以便操作人员无需查看整个系统结构即可进行审计。

Drizzle ORM

将 Drizzle ORM 阶段视为可度量的对象来处理时,其效果最佳。在扩大范围之前,需记录一份完美的操作日志、一个故障案例以及回滚说明。 同时文档化正常流程与恢复流程。重试机制、人工审核环节以及死信处理都是产品本身的一部分,而非后续需要补充的内容。 锁定依赖版本,并记录用于演示的镜像摘要。可重复性远比团队内部的经验更重要。

import { pgTable, serial, varchar, text, integer, timestamp } from "drizzle-orm/pg-core";

// Authors table
export const authors = pgTable("authors", {
  id: serial("id").primaryKey(),
  name: varchar("name", { length: 100 }).notNull(),
  bio: text("bio"),
});

// Books table referencing Authors
export const books = pgTable("books", {
  id: serial("id").primaryKey(),
  title: varchar("title", { length: 150 }).notNull(),
  summary: text("summary"),
  authorId: integer("author_id")
    .notNull()
    .references(() => authors.id),
  publishedAt: timestamp("published_at").defaultNow(),
});

Prisma

将 Prisma 阶段视为可度量的对象来处理时,其效果最佳。在扩大范围之前,需记录一份完美的操作日志、一个故障案例以及回滚说明。 应优先选择小型且可测试的单元,而非庞大的脚本。当某个步骤出现故障时,故障应指向单一的责任模块,而非复杂的流程链。 锁定依赖版本,并记录用于演示的镜像摘要。可重复性远比团队内部的经验更重要。

model Author {
  id    Int     @id @default(autoincrement())
  name  String
  bio   String?
  books Book[]
}

model Book {
  id          Int      @id @default(autoincrement())
  title       String
  summary     String?
  publishedAt DateTime @default(now())
  authorId    Int
  author      Author   @relation(fields: [authorId], references: [id])
}

查询构建

将查询构建阶段视为可度量的工作面,其效果最佳。在扩大范围之前,需记录一份理想案例、一个失败案例以及回滚说明。 应将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,明确成功标准,杜绝默许的半完成状态。 锁定依赖版本,并记录用于演示的镜像摘要。可重复性远胜于经验主义。 将查询构建阶段视为可度量的工作面,其效果最佳。在扩大范围之前,需记录一份理想案例、一个失败案例以及回滚说明。 将配置信息置于应用程序代码之外。环境文件、密钥存储及功能开关应集中存放于一处,以便操作人员无需查看整个架构即可进行审计。

Drizzle ORM

在 Drizzle ORM 阶段,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及错误消息处理都是产品功能的一部分,而非后续需要补充的内容。 在预算允许的情况下,应在持续集成过程中使用测试数据而非真实的付费 API 来添加能够检测关键路径的冒烟测试。

const results = await db
  .select({
    bookId: books.id,
    title: books.title,
    publishedAt: books.publishedAt,
    authorName: authors.name,
  })
  .from(books)
  .leftJoin(authors, eq(books.authorId, authors.id))
  .where(eq(authors.id, authorId))
  .orderBy(books.publishedAt);
const result = await db.transaction(async (tx) => {
  const [newAuthor] = await tx.insert(authors).values({
    name: "Alice",
    bio: "Fantasy author",
  }).returning({ id: authors.id });

  const [newBook] = await tx.insert(books).values({
    title: "The Dream Forest",
    authorId: newAuthor.id,
  }).returning();

  return { newAuthor, newBook };
});

Prisma

在 Prisma 阶段,修改代码之前需明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 优先选择小型、可测试的单元,而非冗长的脚本。当某个步骤失败时,故障应指向单一责任模块,而非复杂的流程链。 在预算允许的情况下,应在持续集成过程中使用测试数据而非真实的付费 API 来添加能够检测关键路径的冒烟测试。

const results = await prisma.book.findMany({
  where: { authorId },
  select: {
    id: true,
    title: true,
    publishedAt: true,
    author: {
      select: { name: true },
    },
  },
  orderBy: { publishedAt: "asc" },
});
const newBook = await prisma.book.create({
  data: {
    title: "The Dream Forest",
    summary: "A surreal adventure.",
    author: {
      create: {
        name: "Alice",
        bio: "Fantasy author",
      },
    },
  },
});

迁移支持

在迁移支持阶段,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 将此阶段视为输入与已验证输出之间的契约。为相关成果命名,定义成功检测标准,并拒绝默许的半完成状态。 在预算允许的情况下,使用测试数据而非真实的付费 API,在持续集成过程中添加用于检测关键路径的冒烟测试。 在迁移支持阶段,应在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放于一个操作人员可以审核的位置,无需查看整个系统结构。

Drizzle ORM

在处理 Drizzle ORM 阶段时,首先需明确相关规范:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及死信处理都是产品功能的一部分,而非后续需要补充的内容。 编写一份简短的操作手册:说明如何轮换密钥、如何清空队列,以及如何回滚上一次的数据导入操作。

npx drizzle-kit generate
npx drizzle-kit migrate
npx drizzle-kit push

Prisma

在处理 Prisma 阶段时,首先需写下相关契约:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 建议使用小型、可测试的单元而非庞大的脚本。当某个步骤失败时,故障应指向单一的责任模块,而非复杂的流程链。 编写简短的操作手册:说明如何轮换密钥、如何清空队列,以及如何回滚上一次的数据导入操作。

npx prisma migrate deploy
npx prisma db push

事务处理

在处理事务处理阶段时,首先需写明契约内容:所需的输入参数、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改始终符合约定。 将此阶段视为输入与已验证输出之间的契约。为相关组件命名,明确成功判定标准,杜绝无声的半完成状态。 编写简短的操作手册:说明如何轮换密钥、如何清空队列、以及如何回滚上一次的数据导入操作。 在处理事务处理阶段时,首先需写明契约内容:所需的输入参数、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改始终符合约定。 将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放于一处,以便操作人员无需查看整个系统结构即可进行审计。

Drizzle ORM

将 Drizzle ORM 阶段视为可度量的对象来处理时,其效果最佳。在扩大范围之前,需记录一份完美的操作日志、一个故障案例以及回滚说明。 同时文档化正常流程与恢复流程。重试机制、人工审核环节以及死信处理都是产品本身的一部分,而非后续需要补充的内容。 锁定依赖版本,并记录用于演示的镜像摘要。可重复性远比团队内部的经验更重要。

await db.transaction(async (tx) => {
  const newAuthor = await tx.insert(authors).values({
    name: "Alice Walker",
    bio: "Pulitzer Prize-winning author",
  }).returning();

  await tx.insert(books).values({
    title: "Journey to the Mountains",
    summary: "A story about adventure and discovery.",
    authorId: newAuthor[0].id,
  });
});

Prisma

将 Prisma 阶段视为可度量的对象来处理时,其效果最佳。在扩大范围之前,需记录一份完美的操作日志、一个故障案例以及回滚说明。 应优先选择小型且可测试的单元,而非庞大的脚本。当某个步骤出现故障时,故障应指向单一的责任模块,而非复杂的流程链。 锁定依赖版本,并记录用于演示的镜像摘要。可重复性远比团队内部的经验更重要。

await prisma.$transaction(async (tx) => {
  const newAuthor = await tx.author.create({
    data: {
      name: "Alice Walker",
      bio: "Pulitzer Prize-winning author",
    },
  });

  await tx.book.create({
    data: {
      title: "Journey to the Mountains",
      summary: "A story about adventure and discovery.",
      authorId: newAuthor.id,
    },
  });
});

性能优势

将“性能优势”阶段视为可度量的对象才能发挥最佳作用。在扩大范围之前,需记录一份理想运行案例、一个故障案例以及回滚说明。 应将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,明确成功标准,绝不允许出现无声的半完成状态。 锁定依赖版本,并记录用于演示的镜像摘要。可重复性远胜于经验主义。 将“性能优势”阶段视为可度量的对象才能发挥最佳作用。在扩大范围之前,需记录一份理想运行案例、一个故障案例以及回滚说明。 将配置信息置于应用程序代码之外。环境文件、密钥存储及功能开关应集中存放,以便操作人员无需查看整个系统结构即可进行审计。

Drizzle ORM

在 Drizzle ORM 阶段,修改代码之前需明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及死信处理都是产品功能的一部分,而非后续需要补充的内容。 在预算允许的情况下,应在持续集成过程中使用测试数据而非真实的付费 API 来添加能够检测关键路径的冒烟测试。

Prisma

在 Prisma 阶段,修改代码之前需明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 相较于庞大的脚本,更应采用小型且可测试的单元。当某个步骤失败时,故障原因应能明确指向某个具体职责,而非整个复杂的流程。 在预算允许的情况下,应在持续集成过程中使用测试数据而非真实的付费 API 来添加能够检测关键路径的冒烟测试。

总结

在“最终确认”阶段,应在修改代码之前明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 将此阶段视为输入与已验证输出之间的契约。为相关成果命名,定义成功判定条件,并拒绝默许的半完成状态。 在预算允许的情况下,使用测试用例而非真实的付费 API,在持续集成过程中对关键路径进行冒烟测试。 在“最终确认”阶段,应在修改代码之前明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放于一个操作人员可审计的位置,无需查看整个系统结构。

操作检查清单

将操作检查清单阶段视为可量化的评估标准,效果最佳。在扩大范围之前,需记录一份最优示例、一个故障案例以及回滚说明。

在功能结果旁记录执行时间以及令牌或查询成本。提前明确成本有助于避免从演示环境过渡到共享环境时出现意外账单。

锁定依赖版本,并记录用于运行演示的镜像摘要。可重复性远胜于个人经验。

将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,明确成功标准,杜绝默许的半完成状态。

编写简短的操作手册:包括如何轮换密钥、如何清空队列以及如何回滚上一次的数据导入操作。

应优先选择小型、可测试的单元,而非庞大的脚本。当某个步骤出错时,故障应能指向单一责任模块,而非复杂的流程链。

在推广该技术栈之前,需冻结版本、为关键路径记录标准输出日志,并确认回滚步骤。共享环境需要设置速率限制、租户验证机制,以及明确的密钥轮换负责人。与其追求花哨的一次性演示,不如注重扎实的可靠性。

针对 63abb6aa882b 的批量说明:请将服务提供商密钥移出代码仓库,设定单会话令牌上限,并将日志存储在评估用示例文件旁,以便后续模型更换时保持数据可比性。