Desenvolvimento com Prisma ORM no Cursor: Um Guia Completo

Prisma é um ORM TypeScript de nova geração que fornece um cliente de banco de dados type-safe, migrações de schema declarativas e um navegador visual de banco de dados chamado Prisma Studio. Prisma elimina código boilerplate de acesso ao banco de dados e captura erros de consulta em tempo de compilação. O Cursor, com seu assistente de IA integrado e base compatível com VS Code, é um excelente editor para desenvolvimento Prisma -- ele fornece IntelliSense para a linguagem de schema do Prisma, auto-completa consultas do Prisma Client e pode gerar schemas completos a partir de descrições em linguagem natural.
Este guia aborda o fluxo de trabalho completo de desenvolvimento com Prisma no Cursor: instalação e configuração, design de schema, migrações, consultas do Prisma Client, relacionamentos, Prisma Studio e geração de schema com IA.
Instalando e Configurando Prisma no Cursor
Pré-requisitos
Prisma funciona com Node.js 18+ e suporta PostgreSQL, MySQL, SQLite, MongoDB e SQL Server. Verifique sua versão do Node.js:
node --version
O terminal integrado do Cursor (Ctrl+`) permanece sincronizado com o painel do Explorer. Você pode executar comandos do Prisma CLI e ver imediatamente os arquivos gerados aparecerem na árvore de arquivos.
Instalando a Extensão Prisma
O Cursor herda a compatibilidade de extensões do VS Code. Instale a extensão oficial Prisma a partir da view de Extensões (Ctrl+Shift+X):
- Pesquise por "Prisma".
- Instale a extensão publicada pela Prisma.
- Recarregue o Cursor se solicitado.
A extensão fornece:
- Realce de sintaxe para arquivos de schema
.prisma. - Formatação automática ao salvar.
- IntelliSense para campos de modelo, atributos e relacionamentos.
- Validação inline para erros de schema.
- Ações de código para correções rápidas.
Se a extensão Prisma não estiver instalada, o Cursor tratará arquivos .prisma como texto puro. Você perderá realce de sintaxe, autocomplete e detecção de erros. Sempre instale a extensão oficial antes de editar arquivos de schema.
Inicializando Prisma em um Projeto
Instale o Prisma CLI e inicialize uma nova configuração Prisma:
npm install prisma --save-dev
npm install @prisma/client
npx prisma init
Isso cria:
prisma/schema.prisma-- o arquivo de schema principal..env-- arquivo de ambiente com um placeholderDATABASE_URL.
Defina sua string de conexão com o banco de dados em .env:
# .env
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"
Peça ao Cursor: "Configure Prisma com PostgreSQL no meu projeto. Crie o arquivo de schema com um modelo User e configure a conexão com o banco de dados." O Cursor executará os comandos init, gerará o schema e configurará o arquivo .env.
Design de Schema
O schema do Prisma é a fonte única de verdade para sua estrutura de banco de dados. Ele define modelos, relacionamentos, enums e configuração de datasource.
Entendendo o Arquivo de Schema
// prisma/schema.prisma
// Generator: diz ao Prisma como gerar o cliente
generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch", "postgresqlExtensions"]
}
// Datasource: conexão com o banco de dados
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
extensions = [pgcrypto, postgis]
}
// Model: mapeia para uma tabela do banco de dados
model User {
id String @id @default(uuid())
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id String @id @default(uuid())
title String
content String?
published Boolean @default(false)
viewCount Int @default(0)
author User @relation(fields: [authorId], references: [id])
authorId String
categories Category[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([authorId])
@@index([published])
}
model Category {
id String @id @default(uuid())
name String @unique
posts Post[]
}
model Profile {
id String @id @default(uuid())
bio String?
user User @relation(fields: [userId], references: [id])
userId String @unique
}
enum Role {
USER
ADMIN
EDITOR
}
Atributos de Campo Comuns
| Atributo | Descrição |
|---|---|
@id | Marca um campo como chave primária |
@default(uuid()) | Gera automaticamente um UUID ao inserir |
@default(autoincrement()) | Inteiro auto-incrementável (MySQL/PostgreSQL) |
@unique | Impõe unicidade no campo |
@updatedAt | Atualiza automaticamente o timestamp ao atualizar registro |
@relation | Define um relacionamento entre modelos |
@map | Mapeia um campo para uma coluna com nome diferente |
@@index | Cria um índice de banco de dados no(s) campo(s) |
@@unique | Restrição única composta |
@@map | Mapeia um modelo para uma tabela com nome diferente |
Peça ao Cursor: "Gere um schema Prisma para uma plataforma de e-commerce com modelos User, Product, Order, OrderItem e Category. Inclua relacionamentos apropriados, índices e enums para status de pedido e disponibilidade de produto." O Cursor produzirá um schema completo e validado com sintaxe de relacionamento correta.
Relacionamentos
Prisma suporta relacionamentos um-para-um, um-para-muitos e muitos-para-muitos.
Relacionamento Um-para-Um:
model User {
id String @id @default(uuid())
profile Profile?
}
model Profile {
id String @id @default(uuid())
user User @relation(fields: [userId], references: [id])
userId String @unique
}
Relacionamento Um-para-Muitos:
model User {
id String @id @default(uuid())
posts Post[]
}
model Post {
id String @id @default(uuid())
author User @relation(fields: [authorId], references: [id])
authorId String
}
Relacionamento Muitos-para-Muitos (implícito):
model Post {
id String @id @default(uuid())
categories Category[]
}
model Category {
id String @id @default(uuid())
posts Post[]
}
Relacionamento Muitos-para-Muitos (explícito, com campos extras na tabela de junção):
model Post {
id String @id @default(uuid())
tags PostTag[]
}
model Tag {
id String @id @default(uuid())
posts PostTag[]
}
model PostTag {
post Post @relation(fields: [postId], references: [id])
postId String
tag Tag @relation(fields: [tagId], references: [id])
tagId String
assignedAt DateTime @default(now())
@@id([postId, tagId])
}
Ao usar relacionamentos muitos-para-muitos implícitos, o Prisma gera automaticamente uma tabela de junção oculta. Você não pode adicionar campos extras (como assignedAt ou createdBy) a esta tabela oculta. Se você precisa de metadados no relacionamento, use uma tabela de junção explícita como mostrado acima.
Migrações
Prisma Migrate cria e aplica mudanças de schema de banco de dados de forma versionada e reversível.
Criando Sua Primeira Migração
Após definir seu schema, crie a migração inicial:
npx prisma migrate dev --name init
Este comando:
- Gera um arquivo de migração SQL em
prisma/migrations/. - Aplica a migração ao seu banco de dados.
- Regenera o Prisma Client.
Use nomes de migração descritivos: npx prisma migrate dev --name add_order_status_enum. Esses nomes aparecem no histórico de migrações e ajudam a rastrear a evolução do schema.
Modificando o Schema
Quando você muda o schema, cria uma nova migração:
# Após editar schema.prisma
npx prisma migrate dev --name add_post_view_count
Prisma detecta a diferença entre seu schema e o banco de dados, gera uma migração e a aplica.
Workflow de Migração para Produção
Para bancos de dados de produção, use prisma migrate deploy que aplica migrações pendentes sem redefinir dados:
# Aplicar migrações em produção
npx prisma migrate deploy
Nunca execute prisma migrate dev contra um banco de dados de produção. O comando dev pode redefinir o banco de dados se detectar desvio de schema. Sempre use migrate deploy em ambientes de produção.
Redefinindo o Banco de Dados
Durante o desenvolvimento, pode ser necessário redefinir o banco de dados e reaplicar todas as migrações:
npx prisma migrate reset
Isso descarta todos os dados e tabelas, depois reaplica todas as migrações do zero.
Populando o Banco de Dados
Crie um script de seed para popular seu banco de dados com dados iniciais:
// prisma/seed.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
// Criar usuários
const alice = await prisma.user.create({
data: {
name: 'Alice Johnson',
role: 'ADMIN',
profile: {
create: {
bio: 'Software engineer and blogger',
},
},
},
});
const bob = await prisma.user.create({
data: {
name: 'Bob Smith',
role: 'USER',
},
});
// Criar posts
const post1 = await prisma.post.create({
data: {
title: 'Getting Started with Prisma',
content: 'Prisma is a type-safe ORM...',
published: true,
author: { connect: { id: alice.id } },
},
});
const post2 = await prisma.post.create({
data: {
title: 'Advanced Prisma Relations',
content: 'Relations in Prisma...',
published: true,
author: { connect: { id: alice.id } },
},
});
console.log('Seed data created successfully');
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
Configure o comando de seed em package.json:
{
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
Execute o seed:
npx prisma db seed
Peça ao Cursor: "Crie um script de seed para meu schema Prisma com 5 usuários, 20 posts e 10 categorias. Certifique-se de que alguns posts não estejam publicados e que alguns usuários tenham perfis enquanto outros não." O Cursor gerará um script de seed realista que exercita todos os tipos de relacionamento.
Consultas do Prisma Client
O Prisma Client é o construtor de consultas type-safe gerado automaticamente que substitui modelos ORM tradicionais e SQL bruto.
Instanciando o Cliente
Crie uma instância singleton para evitar múltiplas conexões em desenvolvimento:
// lib/prisma.ts
import { PrismaClient } from '@prisma/client';
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined;
};
export const prisma =
globalForPrisma.prisma ??
new PrismaClient({
log: ['query', 'info', 'warn', 'error'],
});
if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma;
}
Em desenvolvimento com hot module reloading, criar um novo PrismaClient a cada mudança de arquivo causa esgotamento do pool de conexões. O padrão singleton acima previne isso armazenando a instância em cache no globalThis.
Operações CRUD
Criar:
// Criar um único registro
const user = await prisma.user.create({
data: {
name: 'Charlie Brown',
profile: {
create: {
bio: 'New user bio',
},
},
},
});
// Criar múltiplos registros
const users = await prisma.user.createMany({
data: [
],
});
Ler:
// Encontrar um único registro
const user = await prisma.user.findUnique({
include: { profile: true, posts: true },
});
// Encontrar múltiplos registros com filtragem e ordenação
const publishedPosts = await prisma.post.findMany({
where: { published: true },
orderBy: { createdAt: 'desc' },
take: 10,
skip: 0,
include: {
author: {
select: { id: true, name: true, email: true },
},
},
});
// Contar registros
const totalPosts = await prisma.post.count({
where: { published: true },
});
Atualizar:
// Atualizar um único registro
const updatedPost = await prisma.post.update({
where: { id: postId },
data: {
title: 'Updated Title',
viewCount: { increment: 1 },
},
});
// Atualizar múltiplos registros
const result = await prisma.post.updateMany({
where: { published: false, authorId: userId },
data: { published: true },
});
Excluir:
// Excluir um único registro
const deletedUser = await prisma.user.delete({
where: { id: userId },
});
// Excluir múltiplos registros
const result = await prisma.post.deleteMany({
where: { authorId: userId, published: false },
});
Filtragem Avançada
const posts = await prisma.post.findMany({
where: {
AND: [
{ published: true },
{
OR: [
{ title: { contains: 'prisma', mode: 'insensitive' } },
{ content: { contains: 'orm', mode: 'insensitive' } },
],
},
],
createdAt: {
gte: new Date('2024-01-01'),
lte: new Date('2024-12-31'),
},
author: {
role: { in: ['ADMIN', 'EDITOR'] },
},
},
orderBy: [{ viewCount: 'desc' }, { createdAt: 'desc' }],
});
Transações
// Transação interativa
const result = await prisma.$transaction(async (tx) => {
const author = await tx.user.create({
});
const post = await tx.post.create({
data: {
title: 'My First Post',
content: 'Hello world',
authorId: author.id,
},
});
await tx.profile.create({
data: {
bio: 'New author profile',
userId: author.id,
},
});
return { author, post };
});
Peça ao Cursor: "Escreva uma transação Prisma que transfere créditos entre dois usuários. Deduza do remetente, adicione ao destinatário e crie um registro de transferência. Reverta se o remetente tiver saldo insuficiente." O Cursor gerará a transação interativa com tratamento de erros adequado.
Paginação
// Paginação baseada em offset
const page = 1;
const pageSize = 10;
const [posts, totalCount] = await prisma.$transaction([
prisma.post.findMany({
where: { published: true },
orderBy: { createdAt: 'desc' },
skip: (page - 1) * pageSize,
take: pageSize,
include: { author: true },
}),
prisma.post.count({ where: { published: true } }),
]);
const totalPages = Math.ceil(totalCount / pageSize);
Prisma Studio
Prisma Studio é um navegador visual de banco de dados que roda no seu navegador. Ele permite visualizar, criar, atualizar e excluir registros sem escrever consultas.
Iniciando o Prisma Studio
npx prisma studio
Isso abre uma interface no navegador em http://localhost:5555 onde você pode:
- Navegar por todos os modelos definidos no seu schema.
- Visualizar registros em uma tabela ordenável e filtrável.
- Criar novos registros com uma interface de formulário.
- Editar registros existentes clicando nas células.
- Excluir registros com um diálogo de confirmação.
- Filtrar e buscar registros por valores de campo.
Prisma Studio é inestimável para debugging durante o desenvolvimento. Em vez de escrever consultas descartáveis, inicie o Studio, inspecione seus dados e faça edições rápidas. Ele reflete mudanças em tempo real.
Prisma Studio escreve diretamente no seu banco de dados. Tenha cuidado ao usá-lo contra um banco de dados de produção -- não há desfazer para exclusões ou edições. Sempre faça backup dos seus dados antes de fazer alterações manuais no Studio.
Filtragem no Studio
Prisma Studio suporta filtragem por:
- Nome do campo (selecione qualquer coluna).
- Operador de filtro (igual, diferente, contém, começa com, termina com, etc.).
- Múltiplos filtros combinados com lógica AND/OR.
Geração de Schema com IA no Cursor
O assistente de IA do Cursor se destaca em gerar schemas Prisma, consultas e estratégias de migração a partir de descrições em linguagem natural.
Gerando um Schema a partir de uma Descrição
Abra o Cursor Chat (Ctrl+L) e descreva seu modelo de dados:
Generate a Prisma schema for a project management application with these models:
- User (id, email, name, avatar, role enum: ADMIN/MEMBER/VIEWER)
- Workspace (id, name, slug, ownerId)
- Project (id, name, description, workspaceId, status enum)
- Task (id, title, description, status, priority, assigneeId, projectId, dueDate)
- Comment (id, content, authorId, taskId)
- Label (id, name, color, projectId)
Include all necessary relations, indexes on foreign keys, and timestamps.
Use PostgreSQL with UUID primary keys.
O Cursor gerará um schema completo com todos os modelos, relacionamentos, enums e índices. O schema gerado inclui modelos User, Workspace, Project, Task, Comment e Label com relacionamentos de chave estrangeira adequados, restrições únicas compostas e índices de banco de dados em todas as colunas de chave estrangeira.
Ao pedir ao Cursor para gerar schemas, especifique o provedor de banco de dados (PostgreSQL, MySQL, etc.), o tipo de chave primária (UUID vs. autoincrement) e se você precisa de índices. Isso garante que o schema gerado use recursos específicos do banco de dados corretamente.
Geração de Consultas com IA
Peça ao Cursor para escrever consultas complexas:
Write a Prisma query to fetch the top 5 most active users in a workspace,
sorted by the number of completed tasks. Include each user's name, email,
avatar, and task count. Only count tasks created in the last 30 days.
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const topUsers = await prisma.user.findMany({
where: {
assignedTasks: {
some: {
status: 'DONE',
createdAt: { gte: thirtyDaysAgo },
project: { workspaceId },
},
},
},
select: {
id: true,
name: true,
email: true,
avatar: true,
_count: {
select: {
assignedTasks: {
where: {
status: 'DONE',
createdAt: { gte: thirtyDaysAgo },
},
},
},
},
},
orderBy: {
assignedTasks: {
_count: 'desc',
},
},
take: 5,
});
O _count do Prisma com filtragem aninhada pode gerar consultas SQL caras. Sempre verifique o SQL gerado (ative o log de consultas com new PrismaClient({ log: ['query'] })) e adicione índices de banco de dados apropriados para evitar full table scans.
Conclusão
Prisma combinado com o Cursor cria uma experiência de desenvolvimento de banco de dados simplificada. O arquivo de schema declarativo serve como fonte única de verdade, as migrações fornecem um caminho seguro para a evolução do schema, o Prisma Client type-safe captura erros de consulta em tempo de compilação e o Prisma Studio oferece uma interface visual para inspeção de dados. O assistente de IA do Cursor acelera cada passo -- desde a geração de schemas completos para modelos de domínio complexos até a escrita de consultas otimizadas com includes aninhados e agregações. Comece instalando a extensão Prisma, defina seus modelos com relacionamentos e índices adequados, use migrate dev durante o desenvolvimento e migrate deploy em produção, e deixe o Cursor gerar o boilerplate repetitivo para que você possa focar na camada de dados da sua aplicação.