Гид по технологиям

Использование Prisma с Next.js и PostgreSQL

6 min read Разработка Обновлено 08 Jan 2026
Prisma с Next.js и PostgreSQL
Prisma с Next.js и PostgreSQL

Стеклянная призма на коричневом песке во время заката

Что такое Prisma и зачем он нужен

Prisma — это инструмент, который генерирует типизированный клиент для работы с базой данных и предоставляет декларативный слой для управления схемой. Кратко: он уменьшает объём ручного SQL, снижает риск инъекций и делает модели данных портируемыми между СУБД.

Ключевые преимущества:

  • Типизация и автодополнение в IDE.
  • Декларативная схема (schema.prisma) для модели данных.
  • Генерация клиента (@prisma/client) для простых CRUD-операций.

Важно: Prisma — не абсолютное решение для всех задач (см. раздел «Когда Prisma не подходит»).

Создание приложения Next.js

Перед началом убедитесь, что в среде разработки установлены Node.js и npm (или yarn). Создайте приложение Next.js командой:

npx create-next-app prisma-next

Перейдите в каталог проекта и запустите сервер разработки:

cd prisma-next
npm run dev

По умолчанию dev-сервер будет доступен по адресу http://localhost:3000.

Установка Prisma и генерация клиента

Установите пакеты prisma и @prisma/client:

npm install prisma @prisma/client

Инициализируйте Prisma — это создаст файл schema.prisma и .env:

npx prisma init

Файл .env будет содержать место для строки подключения к базе данных.

Добавление строки подключения к PostgreSQL

Строка подключения имеет формат:

postgres://{username}:{password}@{hostname}:{port}/{database-name}

Сохраните её в .env в переменной DATABASE_URL, например:

DATABASE_URL="postgres://user:pass@localhost:5432/mydb"

В schema.prisma укажите источник данных:

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

generator client {
  provider = "prisma-client-js"
}

Примечание: в provider принято использовать строчные буквы “postgresql”.

Определение схемы данных

В schema.prisma добавьте модель User:

model User {
  id    String @id @default(cuid())
  name  String?
  email String @unique
}

Затем примените схему к базе данных командой push (создаёт таблицы без миграций) или используйте миграции через prisma migrate:

# быстрое создание таблиц
npx prisma db push

# если планируете миграции под версионирование
npx prisma migrate dev --name init

Генерация Prisma Client

После изменения схемы сгенерируйте клиент:

npx prisma generate

Создание клиента в Next.js (lib/prisma.js)

Рекомендуется создавать единственный экземпляр PrismaClient, чтобы избежать проблем с множественными подключениями в режиме разработки. Создайте файл lib/prisma.js со следующим кодом:

import { PrismaClient } from "@prisma/client"

let prisma

if (typeof window === "undefined") {
  if (process.env.NODE_ENV === "production") {
    prisma = new PrismaClient()
  } else {
    if (!global.prisma) {
      global.prisma = new PrismaClient()
    }
    prisma = global.prisma
  }
}

export default prisma

Этот паттерн предотвращает создание новых подключений при горячей перезагрузке в dev-среде.

API-роут для создания пользователя (pages/api/db/createuser.js)

Создайте API-эндпойнт, который принимает POST-запросы и создаёт пользователя в базе. Вариант для папки pages/api:

import prisma from "@/lib/prisma"

export default async function handler(req, res) {
  if (req.method !== "POST") {
    return res.status(405).json({ error: "Method not allowed" })
  }

  const { name, email } = req.body

  try {
    const newUser = await prisma.user.create({
      data: {
        name,
        email,
      },
    })

    res.status(201).json({ user: newUser, error: null })
  } catch (error) {
    res.status(400).json({ error: error.message, user: null })
  }
}

Примечания:

  • Используем POST и req.body (а не req.query), чтобы передавать данные из тела запроса.
  • Возвращаем корректные HTTP-статусы: 201 при создании, 400 при ошибке, 405 для неподдерживаемых методов.

Клиентская форма (app/profile/page.js)

Пример простого клиентского компонента с формой (App Router) — файл app/profile/page.js или pages/profile.js, но если вы используете app-рутер, компонент должен быть клиентским (“use client”):

"use client"
import React, { useState } from "react"

export default function Page() {
  const [name, setName] = useState("")
  const [email, setEmail] = useState("")
  const [error, setError] = useState(null)
  const [loading, setLoading] = useState(false)

  const handleSubmit = async (e) => {
    e.preventDefault()
    setLoading(true)
    setError(null)

    try {
      const res = await fetch('/api/db/createuser', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name, email }),
      })

      const data = await res.json()

      if (!res.ok) {
        throw new Error(data.error || 'Request failed')
      }

      // Успешно: можно очистить форму или показать сообщение
      setName('')
      setEmail('')
    } catch (err) {
      setError(err.message)
    } finally {
      setLoading(false)
    }
  }

  return (
    
setName(e.target.value)} /> setEmail(e.target.value)} /> {error &&
Error: {error}
}
) }

Главные улучшения по сравнению с типичными ошибками:

  • Используем корректные типы input (text/email).
  • onChange обновляет состояние через e.target.value.
  • Заголовок Content-Type и метод POST в fetch.

Частые операции Prisma — шпаргалка

Примеры основных методов Prisma Client (с учётом модели User):

// Найти всех пользователей
const users = await prisma.user.findMany()

// Найти одного по email
const user = await prisma.user.findUnique({ where: { email: 'a@b.com' } })

// Обновить пользователя
const updated = await prisma.user.update({ where: { id: userId }, data: { name: 'New' } })

// Удалить пользователя
const deleted = await prisma.user.delete({ where: { id: userId } })

Эти операции транслируются в безопасные параметризованные SQL-запросы, что защищает от инъекций.

Лучшие практики и безопасность

  • Храните DATABASE_URL в .env и никогда не коммитите его.
  • Для production используйте пул соединений (например PgBouncer) при большом числе подключений.
  • Ограничивайте права пользователя базы данных: предоставьте минимальные привилегии.
  • Валидация на сервере: никогда не доверяйте входным данным с клиента.
  • Логирование ошибок без вывода чувствительных данных в ответ клиенту.

Важно: Prisma генерирует SQL, но ответственность за корректную валидацию и авторизацию остаётся за разработчиком.

Когда Prisma не подходит

  • Если вам нужен тонкий контроль над сложными SQL-оптимизациями или специфическими расширениями PostgreSQL (иногда лучше писать сырой SQL).
  • Если проект критичен к минимальному размеру зависимостей и вы хотите максимально лёгкий стек.
  • Если вам нужна поддержка древних СУБД, для которых Prisma не предоставляет адаптер.

В таких случаях рассмотрите написание собственных репозиториев с SQL/knex или использование легковесных драйверов.

Альтернативы и сравнение (кратко)

  • Sequelize — более старый ORM, поддерживает множество диалектов.
  • TypeORM — активная типизированная альтернатива, иногда сложнее в конфигурации.
  • Objection.js / Knex — уровень ниже (query builder), даёт больше контроля над SQL.

Выбор зависит от привычек команды, требований к миграциям и необходимости типизации.

Ментальные модели при работе с Prisma

  1. Schema.prisma — ваш контракт данных (единственный источник правды для моделей).
  2. prisma generate — компилирует контракт в клиент, который вы импортируете в код.
  3. Клиент — тонкая обёртка над SQL, безопасно подставляет параметры.

Думайте о Prisma как о «типизированном конструкторе запросов», а не как о скрытой БД.

Ролевые чек-листы

Backend-разработчик:

  • Добавил модели в schema.prisma
  • Запустил npx prisma generate
  • Написал API-роуты с проверкой методов и валидацией
  • Обработал ошибки и вернул корректные статусы

Frontend-разработчик:

  • Отправляет запросы методом POST с JSON
  • Обрабатывает ошибки и индикаторы загрузки
  • Не полагается на валидацию только на клиенте

DevOps:

  • Сохраняет DATABASE_URL в защищённых переменных окружения
  • Настроил пул соединений для production
  • Настроил бэкапы и мониторинг для БД

Критерии приёмки

  • Проект стартует и dev-сервер доступен по http://localhost:3000.
  • Prisma сгенерировал клиент и соединение с БД устанавливается (параметры из .env).
  • API /api/db/createuser успешно создаёт запись при POST с { name, email }.
  • На фронте форма корректно отправляет данные и показывает ошибки.

Отладка и частые ошибки

  • “P1001” — проблема подключения к базе: проверьте DATABASE_URL и доступность хоста.
  • Дублирование записей — проверьте уникальные поля и обработку ошибок.
  • Большое количество соединений — используйте пул или PgBouncer.

Пример сценариев тестирования

  • Позитивный: POST /api/db/createuser с валидным email создаёт запись и возвращает 201.
  • Негативный: POST без email возвращает 400 и понятную ошибку.
  • Нагрузочный: одновременные запросы не приводят к исчерпанию соединений (требует мониторинга).

Короткое объявление (для рассылки)

В проекте Next.js реализована интеграция с Prisma и PostgreSQL: добавлена схема User, сгенерирован клиент, настроен API-эндпойнт для создания пользователей и исправлены распространённые ошибки в примерах. Это ускорит разработку и повысит безопасность запросов к БД.

Заключение

Prisma хорошо подходит для большинства приложений на Next.js: он упрощает работу с базой, улучшает UX разработки благодаря типизации и снижает риск SQL-инъекций. Тем не менее стоит понимать его ограничения и дополнять валидацию, авторизацию и инфраструктурные меры (пулы подключений, бэкапы).

Важно: протестируйте поведение в production-подобной среде и настройте мониторинг соединений и ошибок.

Ключевые шаги в одном списке

  1. Установить prisma и @prisma/client
  2. Заполнить DATABASE_URL в .env
  3. Описать модели в schema.prisma
  4. Выполнить npx prisma generate и npx prisma db push (или migrate)
  5. Создать единственный PrismaClient и импортировать его в API
  6. Тестировать и добавить безопасность/логирование
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство