ORM (Mapeo objeto-relación)
El mapeo objeto-relacional (más conocido por su nombre en inglés,
Object-Relational mapping, o sus siglas O/RM, ORM, y O/R mapping) es
una técnica de programación para convertir datos entre el sistema de tipos utilizado en un lenguaje de programación orientado a objetos y la utilización de una base de datos relacional como motor de persistencia. En la práctica esto crea una base de datos orientada a objetos
virtual, sobre la base de datos relacional. Esto posibilita el uso de
las características propias de la orientación a objetos (básicamente herencia y polimorfismo).
Hay paquetes comerciales y de uso libre disponibles que desarrollan el
mapeo relacional de objetos, aunque algunos programadores prefieren
crear sus propias herramientas ORM.
El problema
En la programación orientada a objetos, las tareas de gestión de datos son implementadas generalmente por la manipulación de objetos, los cuales son casi siempre valores no escalares. Para ilustrarlo, considere el ejemplo de una entrada en una libreta de direcciones, que representa a una sola persona con cero o más números telefónicos y cero o más direcciones. En una implementación orientada a objetos, esto puede ser modelado por un "objeto persona" con "campos" que almacenan los datos de dicha entrada: el nombre de la persona, una lista de números telefónicos y una lista de direcciones. La lista de números telefónicos estaría compuesta por "objetos de números telefónicos" y así sucesivamente.Implementaciones
Los tipos de bases de datos usados mayoritariamente son las bases de datos SQL, cuya aparición precedió al crecimiento de la programación orientada a objetos en los 1990s. Las bases de datos SQL usan una serie de tablas para organizar datos. Los datos en distintas tablas están asociados a través del uso de restricciones declarativas en lugar de punteros o enlaces explícitos. Los mismos datos que pueden almacenarse en un solo objeto podrían requerir ser almacenados a través de varias tablas.Una implementación del mapeo relacional de objetos podría necesitar elegir de manera sistemática y predictiva qué tablas usar y generar las sentencias SQL necesarias.
Java Persistence API
Java Persistence API, más conocida por sus siglas JPA, es la API de persistencia desarrollada para la plataforma Java EE.Es un framework del lenguaje de programación Java que maneja datos relacionales en aplicaciones usando la Plataforma Java en sus ediciones Standard (Java SE) y Enterprise (Java EE).La JPA se origina a partir del trabajo del JSR 220 Expert Group el cual correspondía a EJB3. JPA 2.0 sería el trabajo del JSR 317 y posteriormente JPA 2.1 en el JSR 338.
Persistencia en este contexto cubre tres áreas:
- La API en sí misma, definida en el paquete
javax.persistence
- El lenguaje de consulta Java Persistence Query Language (JPQL).
- Metadatos objeto/relacional.
Entidades JPA
Una entidad de persistencia es una clase de Java ligera, cuyo estado es persistido de manera asociada a una tabla en una base de datos relacional. Las instancias de estas entidades corresponden a un registro (conjunto de datos representados en una fila) en la tabla. Normalmente las entidades están relacionadas a otras entidades, y estas relaciones son expresadas a través de meta datos objeto/relacional. Los meta datos del objeto/relacional pueden ser especificados directamente en el fichero de la clase, usando las anotaciones de Java, o en un documento descriptivo XML, el cual es distribuido junto con la aplicación.JPA - Las Relaciones
Antes de comenzar y para entender bien las diferentes relaciones entre entidades debemos tener claro los siguientes conceptos.Rol: Define cual de las entidades de la relación es origen y cuál es la entidad destino.
Dirección: Define si la relación entre dos entidades es unidireccional o bidireccional. Es decir, si existe la relación en ambos sentidos o solamente en uno de ellos y en este segundo caso identifica a la entidad origen y destino.
Cardinalidad: Indica la cantidad de entidades que existen en cada lado de la
relación. Puede ser uno o muchos
Ordinalidad: Indica si un atributo es obligatorio o opcional
Columnas de Unión: En términos de base de datos una relación entre dos tablas significa
que una tabla referencia a otra tabla. Una columna que referencia a una clave
primaria de otra tabla se denomina “clave externa”.
En JPA estas columnas las llamamos “columnas de unión” y la anotación
@JoinColum es utilizada para configurar este tipo de columnas
Las Relaciones:A partir de estos conceptos definimos 4 tipos principales de relaciones entre entidades:
- Muchos a Uno
- Uno a Uno
- Uno a Muchos
- Muchos a Muchos
Muchos a Uno
La
relación entre las entidades Empleados y Departamentos puede ser definida de
este tipo porque Muchos Empleados pueden tener Un Departamento
@ManyToOne
identifica una relación de este tipo y debe aparecer en la entidad origen
La
anotación @ManyToOne identifica siempre el lado propietario de la relación, así
que si hay una “columna de unión” la anotación @JoinColum debe aparecer en esta
misma entidad
El lado propietario de la relación se identifica porque lleva la anotación @JoinColum
El lado inverso o no propietario se identifica porque no lleva esta anotación
@Entity public class Employee { @Id private long id; @ManyToOne @JoinColumn(name="DEPT_ID") private Department department; }
Uno a Uno
La Relación entre Empleado y plaza de parking puede ser definida de este tipo porque un empleado tiene una única plaza de parking y la plaza de parking no puede ser compartida por otro empleadoEn este caso utilizamos la anotación @OneToOne en la entidad Empleado en conjunción con la anotación @JoinColum similar a como hemos definido en el caso anterior
@Entity public class Empleado { @Id private long id; @OneToOne @JoinColumn(name="PSPACE_ID") private ParkingSpace parkingSpace; }
Relaciones Bidireccionales
En ocasiones nos puede interesar
convertir la relación anterior en bidireccional de modo que ambas entidades
tengan conocimiento de la otra.
Para conseguirlo debemos añadir de nuevo la anotación @OneToOne en
este caso a la propiedad Empleado de la entidad Parking
El elemento mappedBy se añade a la notación @OneToOne de la entidad no
propietaria (Parking) haciendo referencia al atributo de la entidad propietaria
de la relación (Empleado)
@Entity public class ParkingSpace { @Id private long id; private int lot; private String location; @OneToOne(mappedBy="parkingSpace") private Employee employee; }
Relaciones de Colecciones
Son aquellas en las que la entidad destino de la relación es múltiple. Es decir “Uno a Muchos ” o “Muchos a Muchos”Uno a Muchos
La
relación entre las entidades Departamentos y Empleados puede ser definida de
este tipo desde el punto de vista de los Departamentos porque Un Departamento
tiene Muchos Empleados.
Normalmente
las relaciones de este tipo son bidireccionales. Es decir por un lado tenemos
una relación Muchos a Uno y para el lado inverso tenemos una relación Uno a
Muchos
El elemento mappedBy se añade a la anotación @OneToMany de la entidad
no propietaria (Departamento) haciendo referencia a la propiedad de la entidad
propietaria de la relación (Empleado)
@Entity public class Department { @Id private long id; private String name; @OneToMany(mappedBy="department") private Collection<employee> employees; }
- La entidad propietaria de la relación debe ser la anotada con @ManyToOne y por tanto debe también llevar la anotación @JoinColumn
- La entidad no propietaria debe utilizar el elemento mappedBy para hacer referencia al atributo de la entidad propietaria
Muchos a Muchos
La relación entre Empleados y Proyectos en los que trabaja es una ejemplo
de relación Muchos a Muchos.
La Entidad de Empleados tiene una colección de entidades proyecto con la
que se relaciona y viceversa
- En este caso la anotación @ManyToMany en los dos entidades define esta relación.
- NO existe anotación @JoinColumn en ninguno de los dados de la relación y por tanto no tenemos forma de identificar cual es la entidad propietaria.
- En este caso debemos elegir una de las dos entidades, cualquiera nos sirve para utilizar el elemento mappedBy.
@Entity public class Employee { @Id private long id; private String name; @ManyToMany private Collection<project> projects; } @Entity public class Project { @Id private long id; private String name; @ManyToMany(mappedBy="projects") private Collection<employee> employees; }
No hay comentarios:
Publicar un comentario