OpenWebinars

Bases de Datos

Qué es un ORM

Si no sabes qué es un ORM, en este artículo te aclaramos el concepto y, además, te contamos los motivos para usarlo y la ventajas y desventajas de su uso.

 César Díaz Alcolea

César Díaz Alcolea

EXPERTO DESARROLLO DE APLICACIONES

Lectura 7 minutos

Publicado el 10 de septiembre de 2021

Compartir

ORM son las siglas de O (Object) R (Relational) M (Mapping) que es una técnica de programación que nos permite trabajar con bases de datos relacionales también conocidos como RDMS (Relational Database Management System), como pueden ser SQL Server, Postgresql, MySQL, Oracle…, el cual nos permite convertir nuestros datos de estas bases de datos relacionales a objetos de nuestro lenguaje orientado a objetos.

De esta forma escribimos nuestro código en el lenguaje orientado a objetos, como podría ser C# o Java o el que usemos, y el ORM lo transforma al lenguaje específico de la Base de datos Relacional. Del mismo modo un ORM permite extraer los datos de una Base de Datos y mapearlo a nuestros objetos del lenguaje que estemos usando.

Por qué usar un ORM

Cuando trabajas con un lenguaje orientado a objetos que se conecta a una base de datos relacional, tienes que realizar manualmente el mapeo entre tus objetos y las tablas en las que se leen/guardan los datos. Hacer esto de forma manual es muy tedioso y propenso a errores si no tienes un ORM que lo haga de forma automática, que además ya vienen preparados para distintas Bases de Datos, por si en algún momento necesitases cambiar de motor de Base de Datos.

Veamos un ejemplo en C#, si no usamos un ORM, una query de inserción se puede convertir en algo como esto:

var query = "INSERT INTO Clients (Id,Name,Email) VALUES (@prop1, @Name, @Email)";

SqlConnection cn = new SqlConnection("...");

var command = new SqlCommand(query);

command.Parameters.AddWithValue("@Id","1")
command.Parameters.AddWithValue("@Name","The Name")
command.Parameters.AddWithValue("@Email","email@mail.com")
//goes on for every column...

cn.Open();
command.ExecuteNonQuery();
cn.Close();

En cambio, si hiciéramos uso de un ORM se queda mucho más sencillo, podría ser algo como lo siguiente:

var client = new Client();
cliente.Id = "1";
cliente.Name = "nombre";
cliente.Email = "email";
db.Save(client);

Como puedes ver, usando un ORM tenemos un código más conciso y más fácil de leer. Y además algo que te ocurrirá con frecuencia es que el modelo de Base de Datos cambie. En el ejemplo anterior si en algún momento se añaden campos para esa tabla, como la dirección del cliente o el teléfono, tendríamos que añadir para ambos casos a nuestra clase Client dichas propiedades, pero si no estás usando un ORM tendrías que buscar todas y cada una de las sentencias CRUD (INSERT, SELECT, UPDATE, DELETE) e introducir los campos en cada una de ellas añadiendo los mismos, en cambio con el uso de un ORM, sólo con tener el dato en la propiedad de la clase es suficiente, el método que guarda en Base de Datos (db.Save(client) en el ejemplo) no cambia.

Tal y como hemos mencionado anteriormente, el uso de un ORM te permite abstraerte de la tecnología subyacente del motor de base de datos, con lo que, si en algún momento necesitaras cambiar de Base de Datos, el paso es mucho más sencillo que si no lo usas. Muchas veces es sólo cambiar alguna propiedad de la configuración del ORM y la cadena de conexión.

Imagen 0 en Qué es un ORM

Qué es impedance mismatching

Impedance mismatching es una forma elegante de decir que los modelos de objetos de nuestro lenguaje de programación y los modelos relacionales de las bases de datos no funcionan muy bien juntos. Las Bases de datos representan los datos en formato tabular, mientras que los lenguajes orientados a objetos, como C#, los representan como un gráfico interconectado de objetos. Cargar y almacenar gráficos de objetos utilizando una base de datos relacional tabular nos expone a varios problemas de mismatch (desajuste), veamos alguno de ellos:

  • Granularidad. A veces se tiene un modelo de objetos que tiene más clases que el número de tablas correspondientes en la base de datos (decimos que el modelo de objetos es más granular que el modelo relacional). Imagínate que en tus clases tienes un objeto Dirección, en el que tienes las propiedades propias de la misma, pero en cambio a la hora de guardar en base de datos, te interesa tenerlo junto con los datos de cliente en vez de en una tabla separada, puesto que no vas a reutilizarla

  • Subtipos (herencia). La herencia es un paradigma natural en los lenguajes de programación orientados a objetos. Sin embargo, las Bases de Datos no es un estándar el tener soporte de subtipos, algunas si lo tienen, pero no todas, con lo que dependiendo de con cual trabajes te puedes encontrar con este caso.

  • Identidad. Una Base de datos define la noción de “identidad” como una clave primaria. Los lenguajes OOP, por ejemplo C#, sin embargo, definen tanto la identidad del objeto a.Id==b.Id como la igualdad del objeto a.equals(b) o a==b.

  • Relaciones. Las relaciones se representan como referencias unidireccionales en los lenguajes de orientación a objetos, mientras que en las Bases de Datos utilizan la noción de claves externas (foreign keys). Si se necesitan relaciones bidireccionales en C#, debe definir la asociación dos veces. Además, no se puede determinar la multiplicidad (1 a N, N a N) de una relación mirando el modelo del objeto.

  • Navegación de datos. La forma de acceder a los datos en un lenguaje de programación orientada a objetos, por ejemplo, C#, es fundamentalmente diferente a la forma de hacerlo en una base de datos relacional. En C#, se navega de una asociación a otra recorriendo la red de objetos. Esta no es una forma eficiente de recuperar datos de una base de datos relacional. Normalmente se quiere minimizar el número de consultas SQL y, por tanto, cargar varias entidades mediante JOINs y seleccionar las entidades necesarias antes de empezar a recorrer el grafo de objetos.

  • Diferencias en tipos de datos. Puede darse el caso en que existan diferencias en los tipos de datos entre un lenguaje orientado a objetos y una Base de Datos. Por ejemplo en C# puedes tener una cadena de longitud variable, que si en Base de Datos está como nvarchar(100) te va a dar problemas a la hora de intentar introducir una cadena mayor de 100.

  • Accesibilidad. En un lenguaje orientado a objetos, tenemos la posibilidad de restringir el acceso a ciertos datos del mismo, con el uso de modificadores (private, public, protected…), puesto que es la naturaleza de este tipo de lenguajes. Esto en Bases de Datos no está definido de forma similar.

Ventajas de usar un ORM

  • No tienes que escribir SQL. Trabajas sólo con el lenguaje que ya conoces. Puede ser una desventaja como veremos más adelante.

  • Acelera el desarrollo y reduce costes, puesto que nos permite reusar código, tener nuestro código sincronizado con el modelo de datos y, al contrario.

  • Nos permite cambiar de motor de base de datos de forma sencilla.

  • Aunque depende del ORM que uses, por lo general viene con una serie de características como gestión de conexiones, transacciones, migraciones de modelo de datos, transformación de datos, etc.

  • Sabe transformar tus necesidades de acceso a datos al proveedor de base de datos que necesites.

  • Puede que algunas de las consultas las genere mejor que si las hicieras en la Base de Datos directamente, dependiendo del tipo de consulta, obviamente. Puede ser una desventaja el que te genere las consultas, como veremos más adelante.

  • Se ocupan de prevenirnos de problemas como puede ser un ataque de tipo SQL Injection u otros similares.

Desventajas de usar un ORM

  • Al no tener que escribir tú las consultas, si se trata de algo complejo, puede dar lugar a generar cierto tipo de consultas muy ineficientes.

  • Tienes que aprender cómo utilizarlos, algunos de ellos tienen cierto grado de complejidad y requiere de tiempo para sacarle el partido necesario para trabajar con ellos de forma eficiente.

  • No todos ellos, pero algunos son pesados, lo cual hace que el rendimiento sea mucho peor que si atacaras directamente a la Base de Datos con una consulta. En ciertos escenarios puede que no esté justificada esta merma de rendimiento y necesites realizar las consultas directamente.

  • En algunos de ellos, la configuración inicial es compleja, ralentizando el desarrollo en exceso.

  • Al no “saber” qué está pasando por debajo, ciertos desarrolladores pueden llegar a perder el control o comprensión de lo que está pasando, con lo que puede ser que ocurran consecuencias no deseadas al realizar cierto tipo de acciones. Por eso el abstraerte tanto de la tecnología subyacente puede ser contraproducente, a veces es una ventaja, pero hay que tener cuidado.

¿Cuáles son los ORMs más usados?

En función del lenguaje de programación que estemos usando podremos decantarnos por el uso de uno u otro, una lista con algunos de los más populares por lenguaje podría ser la siguiente:

Si quieres ver ejemplos concretos de uso de un ORM para PHP con Symfony, en el que podrás ver cómo realizar las distintas operaciones CRUD usando esta tecnología, te recomiendo que le des un vistazo al siguiente curso: Consultas Doctrine en Symfony o este otro curso en el que podrás ver cómo usar un ORM pero con Java: Curso de Hibernate y JPA.

Compartir este post

También te puede interesar