ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Drizzle ORM 接入 Postgres.js 驱动:安装、连接与迁移完整指南

Drizzle ORM 接入 Postgres.js 驱动:安装、连接与迁移完整指南 Drizzle ORM 接入 Postgres.js 驱动安装、连接与迁移完整指南【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-ormDrizzle ORM 为 PostgreSQL 提供了多种驱动适配层其中基于 Postgres.js 为核心骨架结合drizzle-orm/src/postgres-js/目录下的真实源码driver/session/migrator完整讲解如何安装依赖、如何创建连接、如何声明表结构与执行查询以及如何安全地运行数据库迁移含max: 1这一关键配置的来龙去脉。读完本文你将能够在一分钟内把一个 Postgres.js 客户端接入 Drizzle ORM并正确配置迁移环境避免常见的 cannot use unsafe transaction 报错。一、安装依赖Postgres.js 驱动适配层所需的依赖分为运行时与开发时两部分。运行时依赖为drizzle-orm与postgres开发时依赖为drizzle-kit用于生成 SQL 迁移文件。仓库 README 给出了 npm / yarn / pnpm 三种包管理器的安装方式# npm npm i drizzle-orm postgres npm i -D drizzle-kit # yarn yarn add drizzle-orm postgres yarn add -D drizzle-kit # pnpm pnpm add drizzle-orm postgres pnpm add -D drizzle-kit在仓库中postgres是适配层的唯一驱动依赖——从 driver.ts 的导入语句import pgClient, { type Options, type PostgresType, type Sql } from postgres可以看出整个适配层直接围绕 postgres.js 的Sql客户端实例构建没有其他数据库驱动耦合。drizzle-kit只用于开发期生成迁移文件不需要打进生产依赖。提示drizzle-orm/postgres-js子路径导出的源码位于 index.ts它对外重新导出driver.ts与session.ts的全部内容迁移器则单独挂在drizzle-orm/postgres-js/migrator子路径下对应 migrator.ts。二、建立连接两种等效的drizzle()调用方式README 给出的最基础连接方式如下import { drizzle } from drizzle-orm/postgres-js; import postgres from postgres; const client postgres(connectionString); const db drizzle(client);这段代码做了两件事先用 postgres.js 的postgres(connectionString)创建一个底层客户端再把它交给drizzle()包装成 Drizzle 的数据库实例。此后db上的.select()、.insert()、.update()、.delete()等查询构建器都会经由该客户端发送到 PostgreSQL。结合 driver.ts 的源码可以看到drizzle()实际上还支持另外几种写法它们完全等价写法一直接传连接字符串不显式创建客户端import { drizzle } from drizzle-orm/postgres-js; const db drizzle(connectionString); // 内部自动调用 postgres(connectionString)写法二配置对象形式可同时传连接参数与 Drizzle 配置const db drizzle({ connection: { url: connectionString, // 这里可以放任意 postgres.js Options例如 max、ssl 等 }, // Drizzle 侧配置logger / schema / casing / cache logger: true, }); // 也支持显式传入已创建的客户端 const client postgres(connectionString, { max: 1 }); const db drizzle({ client, logger: true, });从源码看drizzle()的参数签名支持三类组合(client | string)、(client | string, DrizzleConfig)、以及(DrizzleConfig { connection | client })。当传入配置对象时源码会解构出connection/client并从中提取url与其余 postgres.jsOptions再调用pgClient(url, config)创建实例若只传连接字符串则等价于pgClient(connectionString)。也就是说README 中的简单写法只是这些重载中最直观的一种。此外drizzle()还提供一个命名空间方法drizzle.mock(config?)用于在无真实数据库时构造一个 mock 数据库实例见 driver.ts其返回值的$client类型被标记为$client is not available on drizzle.mock()适合单元测试场景。关于日志、Schema 与日期解析的底层行为值得留意的是 driver.ts 中construct函数做了一些对使用者透明的处理日期解析器覆盖postgres.js 默认会把date/timestamp等类型解析为 JavaScriptDate对象Drizzle 为了保持对日期字符串的完整控制将类型 OID1184timestamptz、1082date、1083time、1114timestamp、1182date、1185timestamptz 数组、1115timestamp 数组、1231numeric 数组以及序列化器114json与3802jsonb统一替换为透传解析器transparentParser即(val) val。这意味着 Drizzle 模式下日期字段返回的是原始字符串/值而非Date对象如需Date应在应用层自行转换。Logger 处理config.logger true时使用内置DefaultLogger传入自定义 Logger 实例时按自定义逻辑执行。Schema关系配置若在DrizzleConfig中传入schema表定义对象源码会通过extractTablesRelationalConfig提取关系元数据从而支持.queryAPI 与关系查询。缓存支持config.cache会挂载到 db 的$cache上并且当缓存提供onMutate回调时会被注册为缓存失效钩子见 driver.ts。construct最终返回的PostgresJsDatabase同时携带$client属性便于需要时直接访问底层 postgres.js 客户端。三、声明表结构并执行查询主文档延伸README 将表结构声明指引到了主文档本仓库中对应的核心模块位于 drizzle-orm/src/pg-core/PostgreSQL 方言核心包含table.ts、schema.ts、columns/、query-builders/等。以下是一个可直接运行的完整示例将连接、建表、插入与查询串起来import { drizzle } from drizzle-orm/postgres-js; import { pgTable, serial, text, timestamp } from drizzle-orm/pg-core; import postgres from postgres; const connectionString postgres://user:passwordlocalhost:5432/dbname; const client postgres(connectionString); const db drizzle(client, { logger: true }); // 1. 声明 users 表 export const users pgTable(users, { id: serial(id).primaryKey(), name: text(name).notNull(), email: text(email).notNull().unique(), createdAt: timestamp(created_at).defaultNow(), }); // 2. 插入 await db.insert(users).values({ name: John, email: johnexample.com }); // 3. 查询 const rows await db.select().from(users); console.log(rows);postgres.js 客户端天然支持.unsafe()动态 SQL 与 prepared statementsDrizzle 在 session.ts 中通过PostgresJsPreparedQuery.execute()将所有构建好的查询语句与参数以client.unsafe(query, params)发送并在有字段映射需求select 或带结果映射的更新/删除时调用.values()获取行数组后用mapResultRow还原为对象结果。事务则基于 postgres.js 的client.begin()实现见 session.ts嵌套事务通过 savepoint 支持见 session.ts。这意味着你在db.transaction(async (tx) { ... })中写的代码会获得真正的 SQL 事务语义。四、运行迁移为什么必须设置max: 1README 特别强调要使用 Drizzle 的migrate()运行迁移必须在 postgres.js 的连接选项中设置max: 1并建议为迁移单独创建一个连接实例import postgres from postgres; import { migrate } from drizzle-orm/postgres-js/migrator; const migrationsClient postgres(connectionString, { max: 1, // 关键迁移需要单连接避免 cannot use unsafe transaction 错误 }); const db drizzle(migrationsClient); await migrate(db, { migrationsFolder: ... });max: 1的含义是让 postgres.js 只维护一条数据库连接。原因是 Drizzle 的迁移流程在内部会开启显式事务BEGIN/COMMIT来逐个执行迁移 SQL而 postgres.js 的unsafe查询在连接池默认max: 10模式下无法保证 same query on the same connection 的语义——即连接池中的不同连接无法共享同一个已开启的事务postgres.js 会因此抛出Cannot use unsafe transaction之类的错误。将max固定为 1 即可保证迁移语句与事务一定落在同一条连接上。从源码看迁移入口 migrator.ts 非常薄migrate()先调用readMigrationFiles(config)来自 migrator.ts 公共迁移基础设施读取migrationsFolder下的迁移文件然后委托给db.dialect.migrate(...)。而 PostgreSQL 方言层的实现位于 dialect.ts它会在目标库创建drizzleschema 与__drizzle_migrations迁移记录表结构为id SERIAL PRIMARY KEY, hash text NOT NULL, created_at bigint读取已应用的最后一条迁移记录然后在一个事务内按时间戳folderMillis依次执行比已应用记录更新的迁移语句并将每条迁移的 hash 与时间写入记录表。因此迁移期间的事务行为对连接数有硬性要求这就是max: 1不可省略的根本原因。另外注意README 建议为迁移单独创建一个连接实例而不是复用业务查询的客户端——业务连接通常需要连接池保持默认max: 10以支撑并发而迁移客户端固定单连接即可两者职责分离更安全。五、迁移配置项补充migrate()的第二个参数config是MigrationConfig类型除了必填的migrationsFolder迁移文件夹路径指向drizzle-kit generate的输出目录还可以按需配置migrationsTable?: string—— 迁移记录表名默认__drizzle_migrationsmigrationsSchema?: string—— 迁移记录表所在 schema默认drizzle会先执行CREATE SCHEMA IF NOT EXISTS。这两个默认值都可以在 dialect.ts 中确认。示例await migrate(db, { migrationsFolder: ./drizzle, migrationsTable: migrations_log, migrationsSchema: app_migrations, });结合 integration-tests/tests/pg/postgres-js.test.ts 中的集成测试可以看到标准的迁移用法测试先用max: 1创建 postgres.js 客户端再以migrate(db, { migrationsFolder: ./drizzle2/pg })执行迁移随后立刻能向迁移创建的表插入数据并查询回读。这验证了上述配置流程的真实可用性。六、迁移文件从哪来配合 drizzle-kit 的完整工作流要产生migrationsFolder指向的迁移文件需要借助开发依赖drizzle-kit安装方式见第一节。常规工作流为# 1. 定义 schema如第三节的 pgTable 声明 # 2. 在 drizzle.config.ts 中配置 schema 路径与数据库连接 # 3. 生成迁移 SQL 文件 npx drizzle-kit generate # 4. 在应用启动阶段或 CI 流程执行迁移 # await migrate(db, { migrationsFolder: ./drizzle });仓库中 integration-tests/drizzle2/pg/ 目录下存放着迁移测试用的 SQL 与 JSON 文件可作为迁移产物形态的参考。生产实践中迁移通常在服务启动时或部署流水线中执行一次业务代码则使用另一套带连接池的客户端实例。七、小结与最佳实践要点建议依赖运行时drizzle-ormpostgres开发时drizzle-kit连接drizzle(client)或drizzle(connectionString)均可配置对象形式可同时传 postgres.js Options 与 Drizzle 配置查询在db上使用.select/.insert/.update/.delete等构建器事务用db.transaction()迁移必须用max: 1的独立客户端调用migrate()否则连接池会导致事务错误迁移配置migrationsFolder必填migrationsTable/migrationsSchema可自定义默认__drizzle_migrations/drizzle日期行为Drizzle 会覆盖 postgres.js 默认日期解析返回原始字符串/值需要Date请在应用层转换最后回顾 README 的核心指引Postgres.js 驱动适配的进一步用法SQL schema 声明、关系查询、完整迁移文档可继续阅读本仓库 drizzle-orm/src/pg-core/ 下的源码与类型定义以及 drizzle-orm/src/migrator.ts 的公共迁移实现。按照本文的配置清单操作你就能获得一条稳定、可生产使用的 Drizzle ORM × Postgres.js 链路。【免费下载链接】drizzle-ormORM项目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表