Назад к блогу
Backend

Prisma ORM: полное руководство по работе с базами данных

Всё о Prisma ORM: схема данных, миграции, связи между таблицами, транзакции, типизация и Prisma Client.

5 января 2026 г.
12 мин чтения
59 просмотров
MOLOTILO

MOLOTILO DIGITAL

Prisma ORM: полное руководство по работе с базами данных

Что такое Prisma

Prisma — современный ORM для Node.js и TypeScript. Он обеспечивает типобезопасный доступ к базе данных, автоматические миграции и удобный Prisma Client для запросов.

Схема данных

Схема Prisma описывает модели и связи:

// prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id        String   @id @default(uuid())
  email     String   @unique
  name      String?
  password  String
  role      Role     @default(USER)
  posts     Post[]
  profile   Profile?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@index([email])
}

model Profile {
  id     String  @id @default(uuid())
  bio    String?
  avatar String?
  user   User    @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId String  @unique
}

model Post {
  id        String     @id @default(uuid())
  title     String
  content   String?
  published Boolean    @default(false)
  author    User       @relation(fields: [authorId], references: [id])
  authorId  String
  categories Category[]
  tags      String[]
  createdAt DateTime   @default(now())
  updatedAt DateTime   @updatedAt

  @@index([authorId])
  @@index([published])
}

model Category {
  id    String @id @default(uuid())
  name  String @unique
  posts Post[]
}

enum Role {
  USER
  ADMIN
  MODERATOR
}

Миграции

# Создание миграции
npx prisma migrate dev --name init

# Применение миграций в production
npx prisma migrate deploy

# Сброс базы данных (dev only)
npx prisma migrate reset

# Генерация Prisma Client
npx prisma generate

# Просмотр данных в браузере
npx prisma studio

Prisma Client — запросы

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// Создание
const user = await prisma.user.create({
  data: {
    email: 'user@example.com',
    name: 'John Doe',
    password: hashedPassword,
    profile: {
      create: {
        bio: 'Developer'
      }
    }
  },
  include: {
    profile: true
  }
});

// Чтение
const users = await prisma.user.findMany({
  where: {
    role: 'ADMIN',
    email: { contains: '@company.com' }
  },
  select: {
    id: true,
    name: true,
    email: true,
    _count: { select: { posts: true } }
  },
  orderBy: { createdAt: 'desc' },
  take: 10,
  skip: 0
});

// Поиск одного
const user = await prisma.user.findUnique({
  where: { email: 'user@example.com' },
  include: {
    posts: {
      where: { published: true },
      orderBy: { createdAt: 'desc' }
    }
  }
});

// Обновление
const updated = await prisma.user.update({
  where: { id: userId },
  data: {
    name: 'New Name',
    profile: {
      update: { bio: 'Updated bio' }
    }
  }
});

// Удаление
await prisma.user.delete({
  where: { id: userId }
});

Связи между таблицами

// One-to-One (User -> Profile)
const userWithProfile = await prisma.user.findUnique({
  where: { id: userId },
  include: { profile: true }
});

// One-to-Many (User -> Posts)
const userWithPosts = await prisma.user.findUnique({
  where: { id: userId },
  include: {
    posts: {
      where: { published: true },
      take: 5
    }
  }
});

// Many-to-Many (Post <-> Category)
const post = await prisma.post.create({
  data: {
    title: 'New Post',
    content: 'Content...',
    authorId: userId,
    categories: {
      connect: [{ id: cat1Id }, { id: cat2Id }]
    }
  }
});

// Вложенные запросы
const postsWithAuthors = await prisma.post.findMany({
  include: {
    author: {
      select: { name: true, email: true }
    },
    categories: true
  }
});

Транзакции

// Интерактивная транзакция
const result = await prisma.$transaction(async (tx) => {
  // Создаём пользователя
  const user = await tx.user.create({
    data: { email, name, password }
  });
  
  // Создаём профиль
  const profile = await tx.profile.create({
    data: { userId: user.id, bio: '' }
  });
  
  // Если что-то пойдёт не так, всё откатится
  return { user, profile };
});

// Batch транзакция
const [users, posts] = await prisma.$transaction([
  prisma.user.findMany(),
  prisma.post.findMany({ where: { published: true } })
]);

Типизация

import { Prisma, User, Post } from '@prisma/client';

// Типы из схемы
type UserWithPosts = Prisma.UserGetPayload<{
  include: { posts: true }
}>;

// Типы для создания
type CreateUserInput = Prisma.UserCreateInput;

// Типы для обновления
type UpdateUserInput = Prisma.UserUpdateInput;

// Использование в функциях
async function createUser(data: CreateUserInput): Promise {
  return prisma.user.create({ data });
}

async function getUserWithPosts(id: string): Promise {
  return prisma.user.findUnique({
    where: { id },
    include: { posts: true }
  });
}

Оптимизация

// Выбирайте только нужные поля
const users = await prisma.user.findMany({
  select: {
    id: true,
    name: true
    // Не загружаем password, posts и т.д.
  }
});

// Пагинация с курсором (эффективнее offset)
const posts = await prisma.post.findMany({
  take: 10,
  cursor: { id: lastPostId },
  skip: 1 // Пропускаем курсор
});

// Подсчёт без загрузки данных
const count = await prisma.user.count({
  where: { role: 'ADMIN' }
});

// Агрегации
const stats = await prisma.post.aggregate({
  _count: true,
  _avg: { viewCount: true }
});

Заключение

Prisma упрощает работу с базами данных благодаря типизации, миграциям и удобному API. Схема как единый источник правды, Prisma Client для типобезопасных запросов, Prisma Studio для визуального управления.

Prisma — это не просто ORM, это полноценный инструментарий для работы с данными. Инвестируйте время в изучение схемы и связей.

PrismaORMБаза данныхTypeScriptPostgreSQL

Понравилась статья?

Подпишитесь на наш блог, чтобы не пропустить новые материалы