← Назад к вопросам
Как реализовать CRUD-методы в Prisma?
1.8 Middle🔥 161 комментариев
#Soft Skills и рабочие процессы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как реализовать CRUD методы в Prisma
Что такое Prisma
Prisma — это современный ORM (Object-Relational Mapping) для Node.js и TypeScript. Он упрощает работу с базами данных, предоставляя типизированный API для выполнения операций CRUD (Create, Read, Update, Delete). Prisma работает с PostgreSQL, MySQL, SQLite и другими БД.
Установка и конфигурация
# Установка Prisma
npm install @prisma/client
npm install -D prisma
# Инициализация проекта
npx prisma init
Файл .env:
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
Определение модели (Schema)
prisma/schema.prisma:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
password String
posts Post[] @relation("UserPosts")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation("UserPosts", fields: [authorId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Применение миграции:
# Создаёт миграцию
npx prisma migrate dev --name init
# Или для продакшена
npx prisma migrate deploy
CREATE — Создание записей
// lib/prisma.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default prisma;
// services/userService.ts
import prisma from '@/lib/prisma';
// Способ 1: Простое создание
export async function createUser(email: string, name: string, password: string) {
const user = await prisma.user.create({
data: {
email,
name,
password,
},
});
return user;
}
// Способ 2: С возвращением выбранных полей
export async function createUserSafe(email: string, name: string, password: string) {
const user = await prisma.user.create({
data: {
email,
name,
password,
},
select: {
id: true,
email: true,
name: true,
createdAt: true,
// password НЕ возвращаем из соображений безопасности
},
});
return user;
}
// Способ 3: Создание с вложенными данными
export async function createUserWithPost(
email: string,
postTitle: string,
postContent: string
) {
const user = await prisma.user.create({
data: {
email,
name: 'New User',
password: 'hashed_password',
posts: {
create: {
title: postTitle,
content: postContent,
published: false,
},
},
},
include: {
posts: true, // Включает посты в результат
},
});
return user;
}
// Способ 4: Массовое создание
export async function createManyUsers(users: Array<{ email: string; name: string; password: string }>) {
const result = await prisma.user.createMany({
data: users,
skipDuplicates: true, // Пропускает дубликаты
});
return result;
}
READ — Чтение записей
// Получение одной записи по ID
export async function getUserById(id: number) {
const user = await prisma.user.findUnique({
where: { id },
});
return user;
}
// Получение по другому полю
export async function getUserByEmail(email: string) {
const user = await prisma.user.findUnique({
where: { email },
});
return user;
}
// Получение всех пользователей
export async function getAllUsers() {
const users = await prisma.user.findMany();
return users;
}
// С фильтрацией
export async function getUsersByPartialName(namePart: string) {
const users = await prisma.user.findMany({
where: {
name: {
contains: namePart,
mode: 'insensitive', // case-insensitive поиск
},
},
});
return users;
}
// С сортировкой и пагинацией
export async function getUsersPaginated(page: number, pageSize: number) {
const skip = (page - 1) * pageSize;
const users = await prisma.user.findMany({
skip,
take: pageSize,
orderBy: { createdAt: 'desc' },
});
const total = await prisma.user.count();
return {
users,
total,
pages: Math.ceil(total / pageSize),
};
}
// С включением связанных данных
export async function getUserWithPosts(id: number) {
const user = await prisma.user.findUnique({
where: { id },
include: {
posts: {
orderBy: { createdAt: 'desc' },
take: 10, // Последние 10 постов
},
},
});
return user;
}
// Выбор определённых полей
export async function getUserPreview(id: number) {
const user = await prisma.user.findUnique({
where: { id },
select: {
id: true,
name: true,
email: true,
createdAt: true,
posts: {
select: {
id: true,
title: true,
},
take: 5,
},
},
});
return user;
}
UPDATE — Обновление записей
// Обновление по ID
export async function updateUser(
id: number,
data: { name?: string; email?: string }
) {
const user = await prisma.user.update({
where: { id },
data,
});
return user;
}
// Условное обновление
export async function updateUserEmail(id: number, newEmail: string) {
const user = await prisma.user.update({
where: { id },
data: {
email: newEmail,
updatedAt: new Date(), // Автоматически обновляется
},
});
return user;
}
// Массовое обновление
export async function publishAllPostsByUser(userId: number) {
const result = await prisma.post.updateMany({
where: { authorId: userId },
data: { published: true },
});
return result;
}
// Update или Create (Upsert)
export async function upsertUser(email: string, name: string) {
const user = await prisma.user.upsert({
where: { email },
update: { name },
create: {
email,
name,
password: 'default_password',
},
});
return user;
}
DELETE — Удаление записей
// Удаление по ID
export async function deleteUser(id: number) {
const user = await prisma.user.delete({
where: { id },
});
return user;
}
// Массовое удаление
export async function deleteOldUsers(beforeDate: Date) {
const result = await prisma.user.deleteMany({
where: {
createdAt: {
lt: beforeDate, // lt = less than
},
},
});
return result;
}
// Удаление с каскадом
// (конфигурируется в schema.prisma)
// model Post {
// author User @relation(..., onDelete: Cascade)
// }
// При удалении пользователя удалятся все его посты
Практический пример: API endpoint
// pages/api/users/[id].ts
import type { NextApiRequest, NextApiResponse } from 'next';
import prisma from '@/lib/prisma';
type ResponseData = {
data?: any;
error?: string;
};
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
const { id } = req.query;
const userId = Number(id);
try {
// GET - Чтение
if (req.method === 'GET') {
const user = await prisma.user.findUnique({
where: { id: userId },
include: { posts: true },
});
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
return res.status(200).json({ data: user });
}
// PUT - Обновление
if (req.method === 'PUT') {
const { name, email } = req.body;
const user = await prisma.user.update({
where: { id: userId },
data: { name, email },
});
return res.status(200).json({ data: user });
}
// DELETE - Удаление
if (req.method === 'DELETE') {
const user = await prisma.user.delete({
where: { id: userId },
});
return res.status(200).json({ data: user });
}
res.status(405).json({ error: 'Method not allowed' });
} catch (error) {
console.error('Database error:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
Обработка ошибок
import { Prisma } from '@prisma/client';
try {
const user = await prisma.user.create({
data: { email: 'test@example.com', password: 'pwd' },
});
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
// P2002 - Unique constraint failed
if (error.code === 'P2002') {
console.log('Email already exists');
}
// P2025 - Record not found
if (error.code === 'P2025') {
console.log('User not found');
}
}
}
Итоговый принцип
Prisma упрощает CRUD операции через типизированный API. Используй findUnique для поиска по уникальным полям, findMany для списков, create/update/delete для изменения данных. Всегда обрабатывай ошибки и выбирай нужные поля через select или include для оптимизации запросов.