¿Qué es un ORM? Cómo las apps hablan con las bases de datos, explicado
Un ORM (mapeador objeto-relacional) es una biblioteca de código que se sitúa entre una app y una base de datos relacional. En lugar de escribir consultas a la base de datos en SQL, los desarrolladores trabajan con los datos como objetos normales de su lenguaje de programación —db.booking.create(...) o Booking.find(...)— y el ORM traduce eso a SQL, lo ejecuta y convierte los resultados de nuevo en objetos. Ejemplos populares son Prisma y Drizzle para TypeScript, SQLAlchemy para Python y Entity Framework Core para C#.
Por qué importan los ORM cuando construyes con IA
Cuando un constructor de apps con IA añade una base de datos a tu app, normalmente también añade un ORM para hablar con ella. No tendrás que escribir código de ORM, pero conviene saber que está ahí:
- Tu modelo de datos vive en el código. El archivo de esquema del ORM suele ser la descripción más clara de los datos de tu app: qué tablas existen, qué campos tiene cada una y cómo se conectan. Leerlo es una forma rápida de comprobar que la IA entendió tu app.
- Los cambios en la base de datos pasan por migraciones. Cuando pides «añade un número de teléfono a los clientes», la IA actualiza el modelo y crea una migración. Saber esto te ayuda a entender por qué un cambio podría necesitar aplicarse antes de funcionar en directo.
- Seguridad por defecto. Los ORM construyen las consultas de forma que protegen frente a la inyección SQL, uno de los agujeros de seguridad más comunes en apps que montan las consultas a mano.
- Trampas de rendimiento. Los ORM facilitan lanzar por error cientos de consultas pequeñas cuando bastaría con una. Es una causa habitual de páginas lentas en apps construidas con IA.
Una analogía cotidiana
Imagina a un viajero británico y a un tendero japonés que no comparten idioma y se entienden a través de un intérprete.
El viajero (tu app) dice: «Quisiera los tres tés más baratos que tengan». El intérprete (el ORM) lo convierte en japonés preciso (SQL), se lo pasa al tendero (la base de datos) y traduce la respuesta de vuelta al inglés.
El viajero nunca aprende japonés, y para la mayoría de las conversaciones eso no es un problema. Pero para una negociación complicada puede ser útil hablar directamente, y por eso la mayoría de los ORM permiten a los desarrolladores escribir SQL puro cuando hace falta.
Cómo funciona un ORM
Bases de datos como Postgres guardan los datos en tablas de filas y columnas, y se consultan con SQL. Los lenguajes de programación trabajan con objetos: una reserva con una fecha, un cliente y un estado. El ORM relaciona una cosa con la otra:
| Lado de la base de datos | Lado del ORM / código |
|---|---|
Tabla bookings | Modelo Booking |
| Fila | Un objeto de reserva |
Columna starts_at | Campo startsAt |
Clave foránea customer_id | Relación booking.customer |
SELECT, INSERT, UPDATE, DELETE | Métodos find, create, update, delete |
Esas cuatro operaciones son las acciones CRUD sobre las que se construye casi cualquier app.
Ejemplo práctico: reservas con Prisma
Aquí tienes un esquema de Prisma simplificado para una app de reservas de un salón de belleza. Describe dos tablas y cómo se vinculan:
model Customer {
id Int @id @default(autoincrement())
name String
email String @unique
bookings Booking[]
}
model Booking {
id Int @id @default(autoincrement())
startsAt DateTime
service String
customer Customer @relation(fields: [customerId], references: [id])
customerId Int
}
En palabras sencillas: un cliente tiene un nombre, un email único y muchas reservas; cada reserva tiene una hora de inicio, un servicio y pertenece a un solo cliente.
Ahora la app quiere «las próximas reservas de Lena, la más cercana primero»:
const bookings = await db.booking.findMany({
where: {
customer: { email: "lena@example.com" },
startsAt: { gte: new Date() },
},
orderBy: { startsAt: "asc" },
});
El ORM lo convierte en SQL más o menos así, lo ejecuta y devuelve una lista de objetos de reserva:
SELECT b.* FROM "Booking" b
JOIN "Customer" c ON c.id = b."customerId"
WHERE c.email = $1 AND b."startsAt" >= $2
ORDER BY b."startsAt" ASC;
Los $1 y $2 son marcadores de posición: el email y la fecha se envían por separado del texto de la consulta, y eso es lo que evita la inyección SQL.
Migraciones
Si después pides «que los clientes puedan añadir un número de teléfono», la IA añade phone String? al modelo Customer (el ? significa que es opcional) y genera una migración: un pequeño script SQL como ALTER TABLE "Customer" ADD COLUMN "phone" TEXT;. Las migraciones se guardan en orden, así que cada copia de la base de datos puede llevarse a la misma estructura, y se conserva el historial de cambios.
ORM comunes por lenguaje
| Lenguaje | ORM comunes |
|---|---|
| TypeScript / JavaScript | Prisma, Drizzle, TypeORM, Sequelize |
| Python | SQLAlchemy, ORM de Django, SQLModel |
| C# | Entity Framework Core |
| Java | Hibernate (a menudo con Spring Data JPA) |
| Ruby | Active Record |
Los ORM varían en cuánto ocultan el SQL. Prisma usa su propio lenguaje de esquema y su propio estilo de consulta; Drizzle se mantiene deliberadamente cerca de la forma del SQL y, aun así, es tipado. Herramientas más ligeras llamadas constructores de consultas, como Knex o Kysely para TypeScript, ayudan a construir SQL en el código sin convertir las filas en objetos completos.
Términos clave
| Término | Significado |
|---|---|
| Modelo | La definición en código de una tabla y sus campos. |
| Esquema | La descripción completa de todas las tablas, campos y relaciones. |
| Relación | Un vínculo entre modelos, como una reserva que pertenece a un cliente. |
| Migración | Un script versionado que cambia la estructura de la base de datos. |
| Constructor de consultas | Una herramienta más ligera para construir SQL en código sin el mapeo completo a objetos. |
| Problema N+1 | Lanzar una consulta para una lista y luego una más por cada elemento: lento a gran escala. |
| SQL puro | SQL escrito a mano, que se usa cuando el ORM estorba. |
Conceptos erróneos habituales
- «Un ORM es una base de datos». No lo es. Es un traductor. Sigues necesitando una base de datos como Postgres.
- «Con un ORM no hace falta entender tus datos». Las tablas mal diseñadas dan igual de problemas a través de un ORM. Un buen modelo de datos importa más que la herramienta.
- «Los ORM siempre son lentos». Las consultas del día a día van bien. La lentitud suele venir de patrones como las consultas N+1 o de índices que faltan, y eso se puede arreglar.
- «Un ORM significa que nunca hay riesgo de inyección SQL». Los métodos estándar del ORM son seguros, pero el SQL puro en el que se pegan datos que escribe el usuario sigue siendo peligroso.
- «Editar el archivo de esquema cambia la base de datos en vivo». Solo cuando se crea una migración y se aplica a esa base de datos.
Qué pedir a tu constructor de apps con IA
- «Muéstrame el esquema de la base de datos y explica en lenguaje sencillo cada tabla y cada relación.»
- «¿Qué ORM usa este proyecto y dónde están las migraciones?»
- «Antes de cambiar cualquier tabla, dime si los datos existentes se verán afectados, y nunca borres una columna que tenga datos sin preguntarme.»
- «Revisa las páginas más lentas en busca de consultas N+1 y añade índices donde las listas se filtran u ordenan.»
- «Asegúrate de que cada consulta que usa datos del usuario pase por el ORM o use parámetros, sin SQL construido con cadenas de texto.»
ORM en Mythex
Cuando tu app necesita guardar datos, Mythex añade a tu proyecto una base de datos Postgres propia —pídelo en el chat o usa el comando /database— e inyecta sus datos de conexión en el espacio de trabajo y en la app publicada (Base de datos). Después, el agente escribe el código que lee y guarda tus datos. Si tienes una preferencia —«usa Prisma», «usa SQLAlchemy» o «SQL puro, sin ORM»— dilo en el chat. Pídele que te explique el esquema cuando quieras revisar la estructura; puedes leer los archivos en el editor de código. Para ver el panorama general, consulta qué es una base de datos y SQL vs NoSQL.
Preguntas
¿Qué es un ORM en pocas palabras?
Un ORM (mapeador objeto-relacional) es una biblioteca de código que se sitúa entre tu app y una base de datos relacional. Permite a los desarrolladores leer y guardar datos como objetos normales de su lenguaje de programación, y escribe por detrás las consultas SQL.
¿Cuáles son algunos ejemplos de ORM?
Los ORM más comunes son Prisma y Drizzle para TypeScript y JavaScript, SQLAlchemy y el ORM de Django para Python, Entity Framework Core para C#, Hibernate para Java y Active Record en Ruby on Rails.
¿Es mejor un ORM que escribir SQL?
Depende del trabajo. Un ORM hace que las lecturas y escrituras del día a día sean más rápidas de escribir, más seguras y más fáciles de cambiar, mientras que el SQL escrito a mano da control total para informes complejos o consultas críticas para el rendimiento. La mayoría de los ORM te permiten recurrir a SQL puro cuando lo necesitas.
¿Qué es una migración?
Una migración es un script pequeño y versionado que cambia la estructura de la base de datos, por ejemplo al añadir una tabla o una columna. Los ORM pueden generar migraciones a partir de tu modelo de datos para que cada copia de la base de datos —en un portátil, en las pruebas y en producción— acabe con la misma estructura.