PrismaJuniorTechnical
Как структурирована схема Prisma (schema.prisma)? Что такое модели, поля и связи (relations)?
schema.prisma состоит из трёх блоков: datasource (подключение к БД), generator (настройка кодогенерации) и model (описание таблиц с полями, типами и атрибутами). Поля-связи виртуальные — реальные колонки FK создаются через @relation.
Структура файла schema.prisma
Файл schema.prisma — единственный источник истины о структуре БД и настройках Prisma. Он состоит из трёх блоков: datasource, generator и model.
datasource — подключение к базе данных
datasource db {
provider = "postgresql" // postgresql | mysql | sqlite | sqlserver | mongodb | cockroachdb
url = env("DATABASE_URL") // строка подключения из переменной окружения
}
Значение DATABASE_URL обычно хранится в файле .env и имеет формат: postgresql://user:password@localhost:5432/dbname.
generator — настройка генерации клиента
generator client {
provider = "prisma-client-js"
// опционально: выходная директория клиента
output = "../src/generated/prisma"
// опционально: preview-фичи
previewFeatures = ["fullTextSearch", "metrics"]
}
После изменения схемы нужно запустить npx prisma generate, чтобы пересоздать типизированный клиент.
model — описание таблиц
Каждая модель соответствует таблице в БД. Поля объявляются в формате: имя Тип атрибуты:
model User {
id Int @id @default(autoincrement())
email String @unique
name String? // опциональное поле (NULL в БД)
role Role @default(USER) // enum с дефолтом
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
posts Post[] // виртуальное поле-связь
@@index([email]) // индекс на уровне таблицы
@@map("users") // настоящее имя таблицы в БД
}
Типы полей
- Скалярные:
String,Int,Float,Boolean,DateTime,Json,Bytes,BigInt,Decimal - Модели-связи: ссылки на другие модели (
Post[],User?) - Перечисления:
enum Role { USER ADMIN }
Атрибуты полей
model Post {
id Int @id @default(autoincrement()) // первичный ключ, автоинкремент
uuid String @default(uuid()) // UUID по умолчанию
cuid String @default(cuid()) // CUID по умолчанию
title String @db.VarChar(255) // нативный SQL-тип
content String? @db.Text
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
}
Enum
enum Role {
USER
ADMIN
MODERATOR
}
Атрибуты уровня модели
model UserProfile {
userId Int
tenantId Int
data String
@@id([userId, tenantId]) // составной первичный ключ
@@unique([userId, tenantId]) // составной уникальный ключ
@@index([tenantId]) // индекс
@@map("user_profiles") // имя таблицы в БД
}
Полный рабочий пример
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
enum Status {
DRAFT
PUBLISHED
ARCHIVED
}
model Author {
id Int @id @default(autoincrement())
name String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
status Status @default(DRAFT)
authorId Int
author Author @relation(fields: [authorId], references: [id])
@@index([status, authorId])
}
Подводные камни
- Поля-связи (например,
posts Post[]) — виртуальные: они не создают колонок в БД, а используются только в Prisma Client для навигации. Реальная колонка всегда на стороне с@relation(fields: [...]). - Тип
Jsonв PostgreSQL хранится какjsonb, но фильтрация по вложенным ключам JSON в Prisma ограничена. Сложные JSON-запросы лучше выполнять через$queryRaw. @db.VarChar(255)и другие нативные аннотации зависят от СУБД — они нарушают переносимость схемы между PostgreSQL и MySQL.- Переименование модели или поля без
@@map/@mapприведёт к DROP + CREATE таблицы/колонки в миграции, а не к RENAME — это потеря данных. - Enum в PostgreSQL создаётся как отдельный тип. Добавление нового значения в enum — не обратимо совместимая операция в старых версиях PostgreSQL (до 12).
@updatedAtуправляется Prisma на уровне приложения, а не триггером БД. Если запись обновить обходя Prisma (прямым SQL), поле не обновится.- Файл
schema.prismaне поддерживает импорты из других файлов — вся схема должна быть в одном файле (или использовать preview-фичуprismaSchemaFolder).
Common mistakes
- Путает Prisma Client API с гарантиями базы данных: индексы, блокировки и isolation level не создаются магически.
- Не объясняет, где в lifecycle находится schema.prisma, models, fields и relations.
- Не разделяет validation, authorization, business logic и persistence.
- Игнорирует ошибки, лимиты входных данных, observability и тестирование.
What the interviewer is testing
- Может объяснить schema.prisma, models, fields и relations на примере кода.
- Называет ключевые API: model, @id, @relation.
- Отделяет ORM/query builder поведение от реального поведения СУБД.
- Видит production-риски: безопасность, отказоустойчивость, логирование и тесты.