在Nest.js中除Provider外,有无更优雅的Drizzle ORM使用方式?
在Nest.js中优雅使用Drizzle ORM(类似PrismaService的便捷方式)
问题背景
当前使用Drizzle ORM时,需要通过自定义Provider常量(如PG_CONNECTION)注入数据库连接,每次使用都要导入该常量和数据库类型,写法繁琐。希望能像Prisma的PrismaService一样,直接注入一个服务类即可便捷操作。
解决方案:封装DrizzleService
通过创建一个DrizzleService类封装Drizzle实例,替代原有的常量Provider,实现类似PrismaService的简洁用法。
1. 创建DrizzleService
import { Injectable, OnModuleDestroy } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { drizzle } from 'drizzle-orm/postgres-js'; import postgres from 'postgres'; import * as schema from './schema'; @Injectable() export class DrizzleService implements OnModuleDestroy { public readonly db: ReturnType<typeof drizzle<typeof schema>>; private readonly client: ReturnType<typeof postgres>; constructor(private configService: ConfigService) { // 初始化PostgreSQL客户端 this.client = postgres(this.configService.get<string>('DATABASE_URL')); // 初始化Drizzle实例 this.db = drizzle(this.client, { schema }); } // 模块销毁时自动关闭数据库连接 async onModuleDestroy() { await this.client.end(); } }
2. 修改DrizzleModule
将原来的常量Provider替换为DrizzleService,并导出该服务供其他模块使用:
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { DrizzleService } from './drizzle.service'; @Module({ imports: [ConfigModule], providers: [DrizzleService], exports: [DrizzleService], }) export class DrizzleModule {}
3. 在业务服务中使用
现在可以像使用PrismaService一样简洁地注入DrizzleService,直接通过db属性操作数据库:
import { Injectable } from '@nestjs/common'; import { DrizzleService } from '../drizzle/drizzle.service'; @Injectable() export class UsersService { constructor(private drizzleService: DrizzleService) {} async findAll() { return await this.drizzleService.db.query.users.findMany(); } }
进阶优化:直接代理Drizzle实例(可选)
如果希望写法完全贴近PrismaService(无需.db前缀),可以让DrizzleService代理Drizzle实例的所有属性和方法:
import { Injectable, OnModuleDestroy } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { drizzle } from 'drizzle-orm/postgres-js'; import postgres from 'postgres'; import * as schema from './schema'; type DrizzleInstance = ReturnType<typeof drizzle<typeof schema>>; @Injectable() export class DrizzleService implements OnModuleDestroy, DrizzleInstance { private readonly db: DrizzleInstance; private readonly client: ReturnType<typeof postgres>; constructor(private configService: ConfigService) { this.client = postgres(this.configService.get<string>('DATABASE_URL')); this.db = drizzle(this.client, { schema }); // 代理Drizzle实例的所有属性和方法 return new Proxy(this, { get(target, prop) { if (prop in target) { return Reflect.get(target, prop); } return Reflect.get(target.db, prop); }, }); } async onModuleDestroy() { await this.client.end(); } // 声明核心属性以满足TypeScript类型检查 get query() { return this.db.query; } get select() { return this.db.select; } }
此时业务服务中的用法就和PrismaService完全一致:
import { Injectable } from '@nestjs/common'; import { DrizzleService } from '../drizzle/drizzle.service'; @Injectable() export class UsersService { constructor(private drizzle: DrizzleService) {} async findAll() { return await this.drizzle.query.users.findMany(); } }
内容的提问来源于stack exchange,提问作者kilian.sch
相关产品推荐
相关产品推荐

