Prisma ORM v7
Versión estable lanzada en noviembre de 2025. El cambio más significativo de la historia de Prisma: motor completamente libre de Rust, reescrito en TypeScript, con ESM nativo y Driver Adapters obligatorios.
Aunque Prisma ORM v7 está principalmente orientado hacia TypeScript, en esta sección nos centraremos en aquellos aspectos para el desarrollo en Javascript.
¿Qué cambia respecto a la versión anterior?
Prisma v7 es una versión mayor con cambios disruptivos. Los más relevantes son:
| Aspecto | v6 | v7 |
|---|---|---|
| Motor de consultas | Rust (binarios nativos) | TypeScript / WebAssembly (sin Rust) |
| Módulo JS | CommonJS | ESM (ES Modules) nativo |
| Driver Adapters | Opcional (preview) | Obligatorio |
| Generación del cliente | node_modules/@prisma/client | Ruta personalizada obligatoria |
| Config del datasource | schema.prisma | prisma.config.ts (nuevo estándar) |
| Variables de entorno | Cargadas automáticamente desde .env | Requieren carga explícita (dotenv) |
| MongoDB | Soportado | No soportado aún (próximamente) |
Middleware ($use) | Disponible | Eliminado (usar Client Extensions) |
Instalación
Requisitos previos:
- Node.js 20.19.0 o superior (recomendado 24+)
- TypeScript 5.4.0 o superior (recomendado 5.9.x)
- Un proyecto Node.js inicializado (
npm init -y)
Instalación de paquetes
npm install @prisma/client@7
npm install -D prisma@7
Driver Adapter según base de datos
En v7 es obligatorio instalar el adaptador correspondiente al motor de base de datos:
# PostgreSQL
npm install @prisma/adapter-pg pg
# MySQL
npm install @prisma/adapter-mysql mysql2
# SQLite
npm install @prisma/adapter-better-sqlite3 better-sqlite3
Inicializar Prisma
npx prisma init
En v7, prisma init genera automáticamente el archivo prisma.config.js (o .ts si el proyecto usa TypeScript) además del esquema.
Configuración de la base de datos
Variables de entorno
En v7, Prisma ya no carga automáticamente el archivo .env. Es necesario instalarlo y cargarlo de forma explícita:
npm install dotenv
Al inicio del punto de entrada de la aplicación:
import "dotenv/config";
El archivo .env sigue siendo el lugar recomendado para almacenar la URL de conexión:
DATABASE_URL="postgresql://usuario:contraseña@localhost:5432/mi_bd"
Archivo de configuración (obligatorio en v7)
Este archivo reemplaza la configuración del datasource en schema.prisma. Debe colocarse en la raíz del proyecto.
import "dotenv/config";
import { defineConfig } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: process.env["DATABASE_URL"],
},
});
Con shadowDatabaseUrl (para migraciones):
export default defineConfig({
schema: "prisma/schema.prisma",
datasource: {
url: process.env.DATABASE_URL,
shadowDatabaseUrl: process.env.SHADOW_DATABASE_URL,
},
});
Configuración de package.json para ESM
Prisma v7 requiere que el proyecto use ES Modules:
{
"type": "module"
}
Creación de modelos
Cambios en el bloque generator
En v7, el proveedor cambia de prisma-client-js a prisma-client, y el campo output es obligatorio:
generator client {
provider = "prisma-client"
output = "./generated/prisma/client" // obligatorio en v7
}
// El datasource puede seguir en schema.prisma o moverse a prisma.config.js/ts
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
Si defines el datasource en prisma.config.js/ts, la configuración del datasource en el schema se ignora para el CLI.
Definición de modelos
La sintaxis de los modelos es idéntica a la de v6:
model Usuario {
id Int @id @default(autoincrement())
email String @unique
nombre String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
titulo String
contenido String?
publicado Boolean @default(false)
autorId Int
autor Usuario @relation(fields: [autorId], references: [id])
createdAt DateTime @default(now())
}
Tipos de datos y atributos
Sin cambios respecto a v6. Ver sección equivalente en los apuntes de Prisma v6.
Migraciones
Los comandos de migración son los mismos que en v6, pero el CLI toma la configuración desde prisma.config.js/ts:
# Crear y aplicar migración en desarrollo
npx prisma migrate dev --name nombre_migracion
# Aplicar en producción
npx prisma migrate deploy
# Resetear y re-aplicar todo
npx prisma migrate reset
# Sincronizar sin generar migración
npx prisma db push
# Introspección (generar esquema desde BD existente)
npx prisma db pull
El flag --url (eliminado en 7.0) fue restaurado en 7.2.0 para los comandos db pull, db push y migrate dev, permitiendo especificar una URL de conexión diferente a la del config.
npx prisma migrate dev --url postgresql://otro_host/otra_bd
Prisma Client — Configuración y uso
Generar el cliente
npx prisma generate
El cliente se genera en la ruta especificada en el output del generator. Por ejemplo, en ./generated/prisma/client.
Instanciar el cliente con Driver Adapter
En v7 es obligatorio pasar un Driver Adapter al instanciar PrismaClient.
PostgreSQL:
import { PrismaClient } from "./generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg"; // Adaptador de PostgreSQL
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL,
});
export const prisma = new PrismaClient({ adapter });
SQLite:
import { PrismaClient } from "./generated/prisma/client.js";
import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3"; // Adaptador de SQLite
const adapter = new PrismaBetterSqlite3({
url: process.env.DATABASE_URL ?? "file:./dev.db",
});
export const prisma = new PrismaClient({ adapter });
Con Prisma Accelerate (Prisma Postgres):
import { PrismaClient } from "./generated/prisma/client.js";
import { withAccelerate } from "@prisma/extension-accelerate";
export const prisma = new PrismaClient({
accelerateUrl: process.env.DATABASE_URL,
}).$extends(withAccelerate());
Patrón global (para entornos con hot reload)
import { PrismaClient } from "../generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg";
function createPrismaClient() {
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL,
});
return new PrismaClient({ adapter });
}
const globalForPrisma = globalThis;
export const prisma = globalForPrisma.prisma ?? createPrismaClient();
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
Cambio de imports
En v6, el cliente se importaba desde @prisma/client. En v7, se importa desde la ruta generada:
// ❌ v6 (ya no válido en v7)
import { PrismaClient } from "@prisma/client";
// ✅ v7 — JavaScript
import { PrismaClient } from "./generated/prisma/client.js";
Operaciones básicas (CRUD)
Las operaciones CRUD son idénticas en sintaxis a las de v6. La única diferencia práctica es el import y la ausencia de anotaciones de tipo en JavaScript.
Crear registros
// Crear uno
const usuario = await prisma.usuario.create({
data: { email: "ana@ejemplo.com", nombre: "Ana García" },
});
// Crear varios
await prisma.usuario.createMany({
data: [
{ email: "carlos@ejemplo.com", nombre: "Carlos" },
{ email: "marta@ejemplo.com", nombre: "Marta" },
],
skipDuplicates: true,
});
Leer registros
// Por ID único
const usuario = await prisma.usuario.findUnique({
where: { id: 1 },
});
// Primero que coincida
const usuario = await prisma.usuario.findFirst({
where: { nombre: { contains: "García" } },
});
// Todos, con filtros, orden y paginación
const usuarios = await prisma.usuario.findMany({
where: { createdAt: { gte: new Date("2025-01-01") } },
orderBy: { nombre: "asc" },
take: 20,
skip: 0,
include: { posts: true },
});
Actualizar registros
// Actualizar uno
const actualizado = await prisma.usuario.update({
where: { id: 1 },
data: { nombre: "Ana Martínez" },
});
// Upsert
const usuario = await prisma.usuario.upsert({
where: { email: "ana@ejemplo.com" },
update: { nombre: "Ana Actualizada" },
create: { email: "ana@ejemplo.com", nombre: "Ana García" },
});
// Actualizar varios
await prisma.usuario.updateMany({
where: { publicado: false },
data: { publicado: true },
});
Eliminar registros
// Eliminar uno
await prisma.usuario.delete({ where: { id: 1 } });
// Eliminar varios
await prisma.usuario.deleteMany({
where: { createdAt: { lt: new Date("2024-01-01") } },
});
Consultas avanzadas
Filtros lógicos
// AND
const usuarios = await prisma.usuario.findMany({
where: {
AND: [
{ email: { endsWith: "@empresa.com" } },
{ createdAt: { gte: new Date("2025-01-01") } },
],
},
});
// OR
const usuarios = await prisma.usuario.findMany({
where: {
OR: [
{ email: { endsWith: "@empresa.com" } },
{ nombre: { startsWith: "Admin" } },
],
},
});
// NOT
const usuarios = await prisma.usuario.findMany({
where: { NOT: { email: { contains: "spam" } } },
});
Relaciones anidadas
const usuario = await prisma.usuario.create({
data: {
email: "nuevo@ejemplo.com",
nombre: "Nuevo",
posts: {
create: [{ titulo: "Primer post", publicado: true }],
},
},
include: { posts: true },
});
Agregaciones
const total = await prisma.usuario.count();
const stats = await prisma.pedido.aggregate({
_avg: { total: true },
_sum: { total: true },
_max: { total: true },
});
const porEstado = await prisma.pedido.groupBy({
by: ["estado"],
_count: { id: true },
});
Transacciones
// Transacción interactiva
await prisma.$transaction(async (tx) => {
const usuario = await tx.usuario.create({
data: { email: "test@test.com", nombre: "Test" },
});
await tx.post.create({
data: { titulo: "Post test", autorId: usuario.id },
});
});
// Transacción batch
const [usuarios, posts] = await prisma.$transaction([
prisma.usuario.findMany(),
prisma.post.findMany(),
]);
SQL nativo
const resultado = await prisma.$queryRaw`
SELECT nombre FROM "Usuario" WHERE id = ${1}
`;
await prisma.$executeRaw`
UPDATE "Usuario" SET nombre = 'Actualizado' WHERE id = ${1}
`;
Novedades exclusivas de la versión 7
Client Extensions (reemplazo del middleware)
En v7 se elimina la API $use (middleware). El equivalente moderno son las Client Extensions:
// ❌ Middleware (eliminado en v7)
prisma.$use(async (params, next) => {
return next(params);
});
// ✅ Client Extension
const prismaConLog = prisma.$extends({
query: {
usuario: {
async findMany({ args, query }) {
console.log("Consultando usuarios...");
return query(args);
},
},
},
});
Mejoras de rendimiento en TypeScript
Gracias a la colaboración con el creador de ArkType, Prisma v7 genera tipos más eficientes:
- ~98% menos tipos necesarios para evaluar un esquema.
- ~45% menos tipos para evaluar una consulta.
- 70% más rápido en la verificación de tipos completa.
Query Compiler con caché (v7.4+)
El compilador de consultas incluye una capa de caché que evita recompilar consultas con la misma estructura:
// Estas dos consultas tienen la misma "forma" y se benefician del caché
const alice = await prisma.usuario.findUnique({ where: { email: "alice@prisma.io" } });
const bob = await prisma.usuario.findUnique({ where: { email: "bob@prisma.io" } });
// A partir de v7.4, la segunda consulta reutiliza la compilación de la primera
SQL Comments (v7.1+)
Permite añadir metadatos a las consultas SQL para facilitar la observabilidad y el diagnóstico. Los comentarios siguen el formato sqlcommenter de Google:
const usuarios = await prisma.usuario.findMany({
where: { activo: true },
});
Prisma Studio renovado
La nueva versión de Prisma Studio está integrada en el CLI pero es independiente del ORM. Soporta:
- Visualización de relaciones entre tablas.
- Inspección de bases de datos remotas con
--url. - Interfaz más ligera y customizable.
npx prisma studio
npx prisma studio --url postgresql://host/bd_remota
Comandos útiles del CLI
npx prisma init # Inicializar (genera prisma.config.js/ts)
npx prisma generate # Generar/actualizar el cliente
npx prisma migrate dev # Migración en desarrollo
npx prisma migrate dev --url <url> # Migración con URL personalizada (v7.2+)
npx prisma migrate deploy # Aplicar migraciones en producción
npx prisma migrate reset # Resetear la BD
npx prisma db push # Sincronizar esquema sin migraciones
npx prisma db pull # Introspección desde BD existente
npx prisma studio # Abrir Prisma Studio (nueva versión)
npx prisma studio --url <url> # Studio con BD remota
npx prisma format # Formatear schema.prisma
npx prisma validate # Validar schema.prisma