Prisma 7 z adapterami sterowników NestJS i MySQL
Prisma 7 w globalnym module NestJS z MySQL: klient w TypeScript, plik prisma.config.ts oraz adapter sterownika MariaDB, tak skonfigurowane, że każda usługa korzysta z tego samego.
Prisma to ORM dla Node.js i TypeScript, który zarządza schematami, relacjami oraz zapytaniami typowanymi. Prisma 7 zmienia strukturę czasu wykonywania: ścieżka klienta jest w niektórych aspektach prostsza, a w innych bardziej rygorystyczna. Tutaj skupiamy się na konfiguracji Prisma 7 dla usługi NestJS komunikującej się z MySQL – a nie na pełnym szablonie Nest od zera.
Jakie są zmiany?
- Prisma Client nie zawiera już binarnych plików napisanych w języku Rust.
- Ścieżka klienta została przepisana w języku TypeScript i działa w zwykłych środowiskach wykonywania JS.
- Wytwarzane pliki klienta znajdują się w źródle projektu, a nie są ukryte wyłącznie w katalogu
node_modules. - Przegenerowanie klienta nie wymaga już restartowania serwera rozwojowego.
- Pojawił się nowy plik konfiguracyjny Prisma.
- Każda baza danych wymaga adaptera sterownika.
npx prisma studio.- Zainstaluj pakiety Prisma 7:
npm install @prisma/client@7
npm install -D prisma@7
Prisma 7 nie ładowa automatycznie zmiennych środowiskowych. Dodaj plik dotenv:
npm install dotenv
Przykładowe wersje Node i npm użyte we wstępnych instrukcjach konfiguracji:
node -v
v24.11.1
npm -v
11.6.2
- Stwórz początkową strukturę Prisma:
npx prisma init
To tworzy katalog prisma, który zawiera:
schema.prisma— połączenie i modeleprisma.config.ts— konfiguracja.env— zazwyczaj dane do logowania do bazy danych
- Zainstaluj adapter MySQL/MariaDB (adapterzy są ponownie omawiane na końcu):
npm install @prisma/adapter-mariadb
- Konfiguruj adres URL, lokalizację schematu, pliki wyjściowe z migracji oraz dane początkowe. Dokumentacja wymaga pliku
prisma.config.tsw korzeniu projektu obokpackage.json.
.env:
DATABASE_URL="mysql://test_user:test_password@localhost:3306/test_db"
prisma.config.ts:
// This file was generated by Prisma and assumes you have installed the following:
// npm install --save-dev prisma dotenv
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: process.env.DATABASE_URL!
},
});
Częstym problemem jest błąd PrismaConfigEnvError: Brakuje wymaganej zmiennej środowiskowej: DATABASE_URL lub skargi na konieczność użycia źródła danych do wykonywania polecenia prisma db push. Jedna z omawianych tematów to prisma/prisma#28590.
- Ustaw wyjście klienta i zdefiniuj modele w schemacie:
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
moduleFormat = "cjs" //Matches Prisma's output format with NestJS's CommonJS runtime environment.
}
datasource db {
provider = "mysql"
}
// Example model
model user {
id Int @id @default(autoincrement())
email String @unique
name String?
password String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
- Otocz klienta usługą NestJS, która zarządza operacjami połączenia i rozłączenia:
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { PrismaClient } from '../src/generated/prisma/client';
import { PrismaMariaDb } from '@prisma/adapter-mariadb';
@Injectable()
export class PrismaService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy
{
constructor() {
const adapter = new PrismaMariaDb(process.env.DATABASE_URL!);
super({ adapter, log: ['info', 'warn', 'error'] });
}
async onModuleInit() {
try {
await this.$connect();
await this.$queryRaw`SELECT 1`;
console.log('✅ Prisma connected to MySQL');
} catch (error) {
console.error('❌ Prisma connection error:', error);
throw error;
}
}
async onModuleDestroy() {
await this.$disconnect();
console.log('🔌 Prisma disconnected from MySQL');
}
}
- Eksportuj go z modułu globalnego:
import { Module, Global } from '@nestjs/common';
import { PrismaService } from './prisma.service';
@Global()
@Module({
providers: [PrismaService],
exports: [PrismaService],
})
export class PrismaModule {}
- Opcjonalny skrypt nasionowy do danych testowych:
import { PrismaClient } from '../src/generated/prisma/client';
import { PrismaMariaDb } from '@prisma/adapter-mariadb';
import 'dotenv/config';
const adapter = new PrismaMariaDb(process.env.DATABASE_URL!);
const prisma = new PrismaClient({ adapter });
async function main() {
console.log('🌱 Starting database seeding...');
// Check if database already has data
const userCount = await prisma.user.count();
if (userCount > 0) {
console.log('⚠️ Database already contains data. Skipping seed.');
console.log(` Found ${userCount} users in the database.`);
return;
}
console.log('📭 Database is empty. Starting seed...');
// Hash password for users
const hashedPassword = 'test12345';
// Create users
const user1 = await prisma.user.create({
data: {
email: 'robot@gmail.com',
name: 'Mr Robot',
password: hashedPassword,
},
});
console.log('✅ Created users');
}
main()
.catch((e) => {
console.error('❌ Error during seeding:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
- Importuj
PrismaModuledo modułu głównego:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AuthModule } from './modules/auth/auth.module';
import { ConfigModule } from '@nestjs/config';
import { PrismaModule } from 'prisma/prisma.module';
@Module({
imports: [AuthModule, PrismaModule, ConfigModule.forRoot()],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Gdy baza danych jest uruchomiona:
npx prisma generate
npx prisma db push
npx prisma db seed
npm run start:dev
Zignoruj wygenerowane pliki w git:
/src/generated
Przykładowa struktura folderów:
└── 📁backend
└── 📁prisma
├── prisma.module.ts
├── prisma.service.ts
├── schema.prisma
├── seed.ts
└── 📁src
└── 📁generated
└── 📁prisma
└── 📁modules
└── 📁auth
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── main.ts
├── .env
├── .gitignore
├── .prettierrc
├── eslint.config.mjs
├── nest-cli.json
├── package-lock.json
├── package.json
├── prisma.config.ts
├── README.md
├── tsconfig.build.json
└── tsconfig.json
Przeglądaj dane lokalnie:
npx prisma studio
Adaptatory sterowników
Stary Prisma Client opierał się na silniku zapytań Rust, który przekształcał wywołania klienta w SQL i nawiązywał połączenia TCP za pomocą wbudowanych sterowników. Prisma 7 przenosi kompilację do kompilatora zapytań w JavaScript i usuwa te wbudowane sterowniki. Sterowniki bazy danych w JavaScript komunikują się z bazą danych; adaptery sterowników tłumaczą pomiędzy kompilatorem a tymi sterownikami. Dla MySQL/MariaDB należy użyć adaptera mariadb. Aktualną listę dostępnych adapterów znajdziesz w sekcji dokumentacji Prisma poświęconej adapterom sterowników bazy danych.
W architekturze NestJS korzyść wynika z posiadania jednej wspólnej instancji klienta na proces. Tworzenie nowego obiektu PrismaClient w każdym obsługiwaczu żądań powoduje mnożenie się połączeń i utrudnia rozumienie transakcji. Powyższy wzorzec modułu globalnego utrzymuje jeden serwis widoczny dla modułów funkcjonalnych, jednocześnie umożliwiając testom zastąpienie PrismaService wersją symulowaną.
Gdy regenerujesz projekt po edycji schematu, upewnij się, że ścieżka output nadal odpowiada ścieżce importu użytej w pliku prisma.service.ts. Niezgodność pomiędzy wynikiem generatora a ścieżkami importu jest częstą przyczyną błędów „cannot find module” po udanych wykonyaniach polecenia prisma generate. Utrzymuj moduleFormat zgodnie z sposobem kompilacji w NestJS – różnice między CommonJS a ESM objawiają się subtelnymi błędami w czasie wykonywania, a nie wyraźnymi błędami kompilacji.
To wystarczy, aby Prisma 7 mogło komunikować się z MySQL za pośrednictwem NestJS przy użyciu adapterów, plików konfiguracyjnych oraz wygenerowanego klienta znajdujących się w granicach kontroli źródeł.
Literatura pokrewna
- Pierwsze kroki z Prismą w Node.js i PostgreSQL — Zainstaluj Prisamę, utwórz schemat w PostgreSQL, przeprowadź migracje, wygeneruj klienta oraz uruchom pierwsze zapytania odczytu i zapisu.
- Konfiguracja Prismy 7 z Accelerate URLs — Przeanalizuj plik prisma.config.ts, argumenty konstruktora, protokoły accelerateURL oraz ustawienie DATABASE_URL w Prismie 7.