00
:
00
:
00
:
00
Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

Relazioni

Tipi di Relazione

Prisma supporta tre tipi fondamentali di relazione: uno-a-uno (1:1), uno-a-molti (1:N) e molti-a-molti (N:M).

Relazione Uno-a-Uno (1:1)

Un record e’ collegato a esattamente un altro record.

model User {
  id      Int      @id @default(autoincrement())
  email   String   @unique
  profile Profile?
}

model Profile {
  id     Int    @id @default(autoincrement())
  bio    String
  avatar String?
  user   User   @relation(fields: [userId], references: [id])
  userId Int    @unique  // @unique rende la relazione 1:1
}
// Creare utente con profilo
const user = await prisma.user.create({
  data: {
    email: 'mario@example.com',
    profile: {
      create: {
        bio: 'Sviluppatore full-stack',
        avatar: 'https://example.com/avatar.jpg',
      },
    },
  },
  include: { profile: true },
})

Relazione Uno-a-Molti (1:N)

Un record e’ collegato a molti altri record. E’ la relazione piu’ comune.

model User {
  id    Int    @id @default(autoincrement())
  email String @unique
  name  String
  posts Post[]
}

model Post {
  id       Int      @id @default(autoincrement())
  title    String
  content  String?
  author   User     @relation(fields: [authorId], references: [id])
  authorId Int
}
// Creare un utente con piu' post
const user = await prisma.user.create({
  data: {
    email: 'anna@example.com',
    name: 'Anna',
    posts: {
      create: [
        { title: 'Primo post', content: 'Contenuto del primo post' },
        { title: 'Secondo post', content: 'Contenuto del secondo post' },
      ],
    },
  },
  include: { posts: true },
})

// Trovare i post di un utente
const posts = await prisma.post.findMany({
  where: { authorId: 1 },
  include: { author: true },
})

Relazione Molti-a-Molti (N:M)

Relazione Implicita

Prisma crea automaticamente la tabella pivot:

model Post {
  id         Int        @id @default(autoincrement())
  title      String
  categories Category[]
}

model Category {
  id    Int    @id @default(autoincrement())
  name  String @unique
  posts Post[]
}
// Creare un post con categorie
const post = await prisma.post.create({
  data: {
    title: 'Guida Prisma',
    categories: {
      create: [
        { name: 'Database' },
        { name: 'TypeScript' },
      ],
    },
  },
  include: { categories: true },
})

// Collegare categorie esistenti
const updated = await prisma.post.update({
  where: { id: 1 },
  data: {
    categories: {
      connect: [{ id: 3 }, { id: 5 }],
    },
  },
})

Relazione Esplicita

Quando la tabella pivot ha campi aggiuntivi:

model Post {
  id         Int          @id @default(autoincrement())
  title      String
  categories PostCategory[]
}

model Category {
  id    Int            @id @default(autoincrement())
  name  String         @unique
  posts PostCategory[]
}

model PostCategory {
  post       Post     @relation(fields: [postId], references: [id])
  postId     Int
  category   Category @relation(fields: [categoryId], references: [id])
  categoryId Int
  assignedAt DateTime @default(now())
  assignedBy String

  @@id([postId, categoryId])
}

Self-Relation

Un modello puo’ avere una relazione con se stesso, utile per strutture gerarchiche:

model Employee {
  id         Int        @id @default(autoincrement())
  name       String
  managerId  Int?
  manager    Employee?  @relation("ManagerToEmployee", fields: [managerId], references: [id])
  reports    Employee[] @relation("ManagerToEmployee")
}
// Creare un manager con dipendenti
const manager = await prisma.employee.create({
  data: {
    name: 'Marco Rossi',
    reports: {
      create: [
        { name: 'Luca Bianchi' },
        { name: 'Sara Verdi' },
      ],
    },
  },
  include: { reports: true },
})

Relazioni Opzionali

Una relazione opzionale si definisce con ?. Il campo della chiave esterna deve essere anch’esso opzionale:

model Post {
  id       Int   @id @default(autoincrement())
  title    String
  author   User? @relation(fields: [authorId], references: [id])
  authorId Int?  // Nullable: il post puo' non avere un autore
}

Azioni Referenziali (Cascading)

Puoi definire cosa succede quando un record referenziato viene eliminato o aggiornato:

model Post {
  id       Int  @id @default(autoincrement())
  title    String
  author   User @relation(fields: [authorId], references: [id], onDelete: Cascade)
  authorId Int
}

model Comment {
  id     Int  @id @default(autoincrement())
  text   String
  post   Post @relation(fields: [postId], references: [id], onDelete: Cascade, onUpdate: Cascade)
  postId Int
}

Azioni disponibili:

Azione Descrizione
Cascade Elimina/aggiorna anche i record collegati
Restrict Impedisce l’eliminazione se ci sono record collegati
NoAction Simile a Restrict (dipende dal DB)
SetNull Imposta la FK a null (il campo deve essere opzionale)
SetDefault Imposta la FK al valore di default
// Con Cascade: eliminare un utente elimina tutti i suoi post
await prisma.user.delete({
  where: { id: 1 },
  // Tutti i post di questo utente vengono eliminati automaticamente
})