webroad.online
  1. 1Web
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Unelte
  8. 8React
  9. 9State management
  10. 10Next.js
  11. 11Formulare
  12. 12Date și backend
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Animații
  16. 16Testare
  17. 17Arhitectură
Date și backend · Lecția 3 din 4

ORM: Drizzle și Prisma

Scheme în TypeScript, query-uri tipate, migrații; SQL direct vs Drizzle vs Prisma.

Actualizat

Ce este un ORM

Un ORM (Object-Relational Mapper) îți permite să lucrezi cu baza de date prin cod TypeScript în loc de SQL scris ca text. Definești tabelele o dată, ca schemă, iar ORM-ul îți dă:

  • query-uri tipate — autocomplete pe coloane, erori la compilare dacă greșești un nume;
  • migrații — istoric versionat al schimbărilor de structură;
  • protecție implicită contra SQL injection.

Variante de acces la baza de date

Variantă Exemplu Plusuri Minusuri
SQL direct (driver) sql`SELECT ...` cu @neondatabase/serverless control total, zero abstracție fără tipuri automate, migrații manuale
query builder / ORM „SQL-like” Drizzle, Kysely aproape de SQL, tipat, ușor, merge pe edge trebuie să știi SQL
ORM clasic Prisma API foarte simplu, tooling excelent (Studio) abstracție mai groasă, generare de client

Drizzle — schema și query-uri

// shared/api/schema.ts
import { pgTable, serial, text, integer, timestamp } from 'drizzle-orm/pg-core'

export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
})

export const posts = pgTable('posts', {
  id: serial('id').primaryKey(),
  userId: integer('user_id').notNull().references(() => users.id),
  title: text('title').notNull(),
  createdAt: timestamp('created_at').defaultNow().notNull(),
})
import { drizzle } from 'drizzle-orm/neon-http'
import { desc, eq } from 'drizzle-orm'

const db = drizzle(process.env.DATABASE_URL!)

const latest = await db.select().from(posts).where(eq(posts.userId, 1)).orderBy(desc(posts.createdAt)).limit(10)
const [created] = await db.insert(posts).values({ userId: 1, title: 'Salut' }).returning()
type Post = typeof posts.$inferSelect                    // tipul unui rând, din schemă

Observă: userId în cod, user_id în baza de date — maparea camelCase ↔ snake_case e făcută de ORM.

Prisma — aceeași idee, alt stil

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
}
const latest = await prisma.post.findMany({ where: { authorId: 1 }, orderBy: { id: 'desc' }, take: 10, include: { author: true } })

Migrații

O migrație e un fișier care descrie o schimbare de structură (tabel nou, coloană nouă), aplicat o singură dată, în ordine, pe fiecare bază de date (local, preview, producție).

npx drizzle-kit generate    # din schema TS → fișier SQL de migrație
npx drizzle-kit migrate     # aplică migrațiile care nu au rulat încă
Regulă De ce
migrațiile intră în Git aceeași istorie peste tot
nu modifici o migrație deja aplicată creezi una nouă
schimbări „distructive” (redenumire, ștergere coloană) în pași datele existente și codul vechi trebuie să meargă între timp

Unde stau în FSD

Schema și clientul DB → shared/api/. Query-urile unei entități → entities/<x>/api/ (ca entities/lesson/api/lesson-api.ts din proiect). Componentele nu importă niciodată direct clientul DB.

Pe scurt

  • ORM = schemă în TS → query-uri tipate + migrații + protecție la injection.
  • Drizzle = aproape de SQL, ușor; Prisma = API simplu, tooling bogat; SQL direct = control total.
  • Migrațiile sunt versionate în Git și aplicate în ordine, niciodată editate după aplicare.

Surse oficiale

Exerciții

Ți-a fost utilă pagina?

Un click — fără cont.