Prisma
Prisma - это современное ORM (Object Relational Mapping - объектно-реляционное отображение или связывание) для Node.js и TypeScript. Проще говоря,
Prisma
- это инструмент, позволяющий работать с реляционными (PostgreSQL
,MySQL
,SQL Server
,SQLite
) и нереляционной (MongoDB
) базами данных с помощьюJavaScript
илиTypeScript
без использованияSQL
(хотя такая возможность имеется).
Инициализация проекта
Создаем директорию, переходим в нее и инициализируем Node.js-проект
:
mkdir prisma-test
cd prisma-test
yarn init -yp
# or
npm init -y
Устанавливаем Prisma
в качестве зависимости для разработки:
yarn add -D prisma
# or
npm i -D prisma
Инициализируем проект Prisma
:
npx prisma init
Это приводит к генерации файлов prisma/schema.prisma
и .env
.
В файле .env
содержится переменная DATABASE_URL
, значением которой является путь к (адрес) БД. Файл schema.prisma
мы рассмотрим позже.
CLI
Интерфейс командной строки (Command line interface, CLI) Prisma
предоставляет следующие основные возможности (команды):
init
- создает шаблонPrisma-проекта
:--datasource-provider
- провайдер для работы с БД:sqlite
,postgresql
,mysql
,sqlserver
илиmongodb
(перезаписываетdatasource
изschema.prisma
);--url
- адрес БД (перезаписываетDATABASE_URL
)
npx prisma init --datasource-provider mysql --url mysql://user:password@localhost:3306/mydb
generate
- генерирует клиентаPrisma
на основе схемы (schema.prisma
). КлиентPrisma
предоставляет программный интерфейс приложения (Application Programming Interface, API) для работы с моделями и типы дляTypeScript
npx prisma generate
db
pull
- генерирует модели на основе существующей схемы БД
npx prisma db pull
push
- синхронизирует состояние схемыPrisma
с БД без выполнения миграций. БД создается при отсутствии. Используется для прототипировании БД и в локальной разработке. Также может быть полезной в случае ограниченного доступа к БД, например, при использовании БД, предоставляемой облачными провайдерами, такими какElephantSQL
илиHeroku
npx prisma db push
seed
- выполняет скрипт для наполнения БД начальными (фиктивными) данными. Путь к соответствующему файлу определяется вpackage.json
"prisma": {
"seed": "node prisma/seed.js"
}
npx prisma seed
migrate
dev
- выполняет миграцию для разработки:--name
- название миграции
npx prisma migrate dev --name init
Это приводит к созданию БД при ее отсутствии, генерации файла prisma/migrations/migration_name.sql
, выполнению инструкции из этого файла (синхронизации БД со схемой) и генерации (регенерации) клиента (prisma generate
).
Данная команда должна выполняться после каждого изменения схемы.
reset
- удаляет и заново создает БД или выполняет "мягкий сброс", удаляя все данные, таблицы, индексы и другие артефакты
npx prisma migrate reset
deploy
- выполняет производственную миграцию
npx prisma migrate deploy
studio
- позволяет просматривать и управлять данными, хранящимися в БД, в интерактивном режиме:--browser
,-b
- название браузера (по умолчанию используется дефолтный браузер);--port
,-p
- номер порта (по умолчанию -5555
)
npx prisma studio
# без автоматического открытия вкладки браузера
npx prisma studio -b none
Подробнее о CLI
можно почитать здесь.
Схема
В файле schema.prisma
мы видим такие строки:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
datasource
- источник данных:provider
- название провайдера для доступа к БД:sqlite
,postgresql
,mysql
,sqlserver
илиmongodb
(по умолчанию -postgresql
);url
- адрес БД (по умолчанию - значение переменнойDATABASE_URL
);shadowDatabaseUrl
- адрес "теневой" БД (для БД, предоставляемых облачными провайдерами): используется для миграций для разработки (prisma migrate dev
);
generator
- генератор клиента на основе схемы:provider
- провайдер генератора (единственным доступным на сегодняшний день провайдером являетсяprisma-client-js
);binaryTargets
- определяет операционную систему для клиентаPrisma
. Значением по умолчанию являетсяnative
, но иногда это приходится указывать явно, например, при использовании клиента вDocker-контейнере
(в этом случае также приходится явно выполнятьprisma generate
)
generator client {
provider = "prisma-client-js"
binaryTargets = ["native"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}
Для работы со схемой удобно пользоваться расширением Prisma
для VSCode
. Соответствующий раздел в файле settings.json
должен выглядеть так:
"[prisma]": {
"editor.defaultFormatter": "Prisma.prisma"
}
Определим в схеме модели для пользователя (User
) и поста (Post
):
model User {
id String @id @default(uuid()) @db.Uuid
email String @unique
hash String @map("password_hash")
first_name String?
last_name String?
age Int?
role Role @default(USER)
posts Post[]
created_at DateTime @default(now())
updated_at DateTime @updatedAt
@@map("users")
}
model Post {
id String @id @default(uuid())
title String
content String
published Boolean
author_id String
author User @relation(fields: [author_id], references: [id])
created_at DateTime @default(now())
updated_at DateTime @updatedAt
@@map("posts")
}
enum Role {
USER
ADMIN
}
Вот что мы здесь видим:
id
,email
,hash
etc. - названия полей (колонок таблицы);@map
привязывает поле схемы (hash
) к указанной колонке таблицы (password_hash
).@map
не меняет название колонки в БД и поля в генерируемом клиенте. ДляMongoDB
использование@map
для@id
является обязательным:id String @default(auto()) @map("_id") @db.ObjectId
;String
,Int
,DateTime
etc. - типы данных (см. ниже);@db.Uuid
- тип данных, специфичный для одной или нескольких БД (в данном случаеPostgreSQL
);- модификатор
?
после названия типа означает, что данное поле является опциональным (необязательным, может иметь значениеNULL
); - модификатор
[]
после названия типа означает, что значением данного поля является список (массив). Такое поле не может быть опциональным; - префикс
@
означает атрибут поля, а префикс@@
- атрибут блока (модели, таблицы). Некоторые атрибуты принимают параметры; - атрибут
@id
означает, что данное поле является первичным (основным) ключом таблицы (PRIMARY KEY
) (идентификатор модели). Такое поле не может быть опциональным; - атрибут
@default
присваивает полю указанное значение по умолчанию (при отсутствии значения поля) (DEFAULT
). Дефолтными могут быть статические значения (42
,hi
) или значения, генерируем ые функциямиautoincrement
,dbgenerated
,cuid
,uuid
иnow
(функции атрибутов; см. ниже); - атрибут
@unique
означает, что значение поля должно быть уникальным в пределах таблицы (UNIQUE
). Таблица должна иметь хотя бы одно поле@id
или@unique
; - атрибут
@relation
указывает на существование отношений между таблицами. В данном случае между таблицамиusers
иposts
существуют отношения один-ко-многим (one-to-many, 1-n) - у одного пользователя может быть несколько постов (FOREIGN KEY / REFERENCES
) (об отношениях мы поговорим отдельно); - атрибут
@updatedAt
обновляет поле текущими датой и временем при любой модификации записи; - у нас имеется перечисление (enum), значения которого используются в качестве значений поля
role
моделиUser
(значением по умолчанию являетсяUSER
); - атрибут
@@map
привязывает название модели к названию таблицы в БД.@@map
не меняет название таблицы в БД и модели в генерируемом клиенте.