Clase 26 - ORM - Prisma
🤔 ¿Qué es un ORM?
Un ORM (Object-Relational Mapping) es una técnica de programación que permite mapear objetos de un lenguaje de programación a tablas de una base de datos relacional. En esencia, actúa como una capa de abstracción entre tu código TypeScript y la base de datos.
🎯 ¿Para qué sirve un ORM?
- Abstracción de SQL: Permite escribir consultas usando objetos y métodos en lugar de SQL puro, haciendo el código más legible y mantenible.
- Type Safety: En TypeScript, los ORMs proporcionan tipado estático, evitando errores en tiempo de compilación y mejorando la experiencia de desarrollo.
- Productividad: Reduce el boilerplate code necesario para operaciones CRUD básicas.
- Portabilidad: Facilita el cambio entre diferentes sistemas de bases de datos sin reescribir las consultas.
- Prevención de vulnerabilidades: Ayuda a prevenir inyecciones SQL mediante consultas parametrizadas automáticas.
🚀 ORMs populares en TypeScript
1. TypeORM
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()export class User { @PrimaryGeneratedColumn() id: number;
@Column() name: string;
@Column() email: string;}
// Usoconst user = new User();user.name = "Juan";user.email = "juan@example.com";await userRepository.save(user);2. Prisma
// Schema definido en prisma/schema.prismamodel User { id Int @id @default(autoincrement()) name String email String @unique}
// Uso en TypeScriptconst user = await prisma.user.create({ data: { name: "Juan", email: "juan@example.com" }});3. Sequelize
import { DataTypes, Model } from 'sequelize';
interface UserAttributes { id: number; name: string; email: string;}
class User extends Model<UserAttributes> implements UserAttributes { public id!: number; public name!: string; public email!: string;}
User.init({ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, name: { type: DataTypes.STRING, allowNull: false }, email: { type: DataTypes.STRING, allowNull: false, unique: true }}, { sequelize });🧠 ¿Qué es Prisma ORM?
Prisma es un ORM moderno para Node.js y TypeScript que facilita el trabajo con bases de datos relacionales. Permite interactuar con la base de datos usando código TypeScript, evitando la necesidad de escribir consultas SQL manualmente.
✅ Características Clave
-
✨ TypeScript-first: Tipado estático, autocompletado e inferencia automática.
-
⚙️ Schema centralizado: El modelo de datos se define en un único archivo
.prisma. -
🔗 Soporte de relaciones entre tablas muy intuitivo.
-
📦 Prisma Client: Cliente auto-generado y altamente tipado.
-
🔄 Migraciones: Control de versiones del esquema de la base de datos.
-
🧪 Compatibilidad con pruebas y desarrollo local.
🔧 Bases de Datos Compatibles
Prisma es compatible con las siguientes bases de datos relacionales:
-
PostgreSQL
-
MySQL
-
SQLite
-
SQL Server
-
CockroachDB
-
MongoDB (soporte con funciones limitadas)
📦 Instalación y Setup Básico
Paso 1: Inicializar un proyecto
pnpm init -ypnpm add -D prismapnpm prisma initEsto crea:
-
Un archivo
schema.prisma -
Un directorio
prisma/ -
Un archivo
.envcon la URL de conexión
Paso 2: Instalar Prisma Client
pnpm add @prisma/client📄 Prisma Schema: Estructura de schema.prisma
generator client { provider = "prisma-client-js"}
datasource db { provider = "postgresql" url = env("DATABASE_URL")}
model User { id Int @id @default(autoincrement()) name String email String @unique posts Post[]}
model Post { id Int @id @default(autoincrement()) title String content String? author User @relation(fields: [authorId], references: [id]) authorId Int}🔍 Componentes del Schema
| Componente | Descripción |
|---|---|
generator | Define cómo se genera el cliente de Prisma |
datasource | Define la base de datos y la URL de conexión |
model | Define una tabla y sus campos |
@id | Clave primaria |
@default(autoincrement()) | Autoincremento de ID |
@unique | Restricción de unicidad |
@relation | Define relaciones entre tablas |
🔌 Prisma Client: El Puente con la Base de Datos
Prisma Client es una API auto-generada que permite consultar y modificar la base de datos desde tu código.
Ejemplo:
import { PrismaClient } from '@prisma/client'const prisma = new PrismaClient()
// Crear usuarioconst newUser = await prisma.user.create({ data: { name: 'Juan', email: 'juan@example.com', },})
// Consultar usuariosconst users = await prisma.user.findMany()Tipos de Operaciones
-
create,createMany -
findMany,findUnique,findFirst -
update,updateMany -
delete,deleteMany -
upsert -
aggregate,groupBy
🔄 Relaciones Entre Tablas
🔗 1:1
model User { id Int @id @default(autoincrement()) profile Profile?}
model Profile { id Int @id @default(autoincrement()) bio String user User @relation(fields: [userId], references: [id]) userId Int @unique}🔗 1:N
model User { id Int @id @default(autoincrement()) posts Post[]}
model Post { id Int @id @default(autoincrement()) title String author User @relation(fields: [authorId], references: [id]) authorId Int}🔗 N:M (Relación Muchos a Muchos)
model Student { id Int @id @default(autoincrement()) name String courses Course[] @relation("StudentCourses")}
model Course { id Int @id @default(autoincrement()) title String students Student[] @relation("StudentCourses")}model Student { id Int @id @default(autoincrement()) name String courses StudentCourse[]}
model Course { id Int @id @default(autoincrement()) title String students StudentCourse[]}
model StudentCourse { student Student @relation(fields: [studentId], references: [id]) studentId Int @map("student_id")
course Course @relation(fields: [courseId], references: [id]) courseId Int @map("course_id")
@@id([studentId, courseId]) @@map("student_course")}🚦 Migraciones
Prisma permite manejar cambios en la base de datos a través de migraciones:
pnpm prisma migrate dev --name initEsto:
-
Genera el SQL necesario
-
Aplica cambios
-
Actualiza el cliente de Prisma
🧪 Prisma Studio
Interfaz visual para ver y editar datos en tu DB:
pnpm prisma studio📂 Estructura Recomendada del Proyecto
Directorioproject/
Directorioprisma/
- schema.prisma
Directoriomigrations/
- …
Directoriosrc/
- index.ts
- package.json
- .env
🎯 Ejercicio Práctico
Crear un sistema de gestión de biblioteca
-
Modelar entidades:
-
Libro (
Book):id,titulo,autor,publicado,disponible -
Usuario (
User):id,nombre,email -
Préstamo (
Loan):id,user,book,fechaPrestamo,fechaDevolucion
-
-
Definir relaciones:
-
Un
Userpuede tener muchosLoan -
Un
Bookpuede tener muchosLoan
-
-
Usar Prisma Client para:
-
Registrar un nuevo préstamo
-
Consultar libros disponibles
-
Mostrar historial de préstamos por usuario
-