¿Cómo se traducen las relaciones a entidades con anotaciones en JPA?
El mapeo de relaciones en JPA (Java Persistence API) es una pieza esencial para trabajar con bases de datos relacionales. En esta guía, exploraremos cómo implementar diferentes tipos de relaciones entre entidades usando anotaciones como @OneToOne, @ManyToOne y @OneToMany.
El objetivo es que puedas entender cómo estas relaciones se representan en el código para que puedan interactuar eficazmente durante las operaciones de manipulación de datos.
¿Cuáles son los tipos de relaciones más comunes?
Antes de adentrarnos en el código, recordemos los cuatro tipos de tablas que discutimos:
Uno a Uno: Se representa mediante @OneToOne. En nuestro caso, la relación es entre OrderItem y Pixsa, lo que significa que cada OrderItem está asociado con un solo Pixsa.
Uno a Muchos: Se logra con @OneToMany. PixsaOrder puede contener muchos OrderItems.
Muchos a Uno: Utiliza @ManyToOne. Este tipo de relación también se observa entre OrderItem y PixsaOrder, donde múltiples OrderItems pueden asociarse a una sola orden.
Un ejemplo práctico de los códigos de anotaciones es fundamental para visualizar mejor estas relaciones:
// Relación Uno a Uno@OneToOne@JoinColumn(name ="idPixsa", referencedColumnName ="idPixsa", insertable =false, updatable =false)privatePixsaEntity pixsa;
// Relación Muchos a Uno@ManyToOne@JoinColumn(name ="idOrder", referencedColumnName ="idOrder", insertable =false, updatable =false)privateOrderEntity order;
¿Cómo se trabaja con claves primarias compuestas?
Creación de claves compuestas es otra parte vital del trabajo con JPA, donde dos o más atributos forman una clave primaria:
Utilizar la anotación @IdClass es esencial para gestionar estas claves compuestas.
Ejemplo de cómo definimos varias claves:
@IdClass(OrderItemId.class)// Define la clase de clave compuestapublicclassOrderItemEntity{@IdprivateInteger idOrder;@IdprivateInteger idItem;// Métodos adicionales (equals, hashCode) para asegurar consistencia}
¿Cómo se implementan las anotaciones para asegurar integridad referencial?
En la integración de estas relaciones, la integridad y el rendimiento son cruciales. Utilizar @JoinColumn es importante. Se usa para especificar la columna a través de la cual están vinculadas dos tablas.
Por ejemplo, se puede definir la relación OneToMany como sigue:
Aquí, mappedBy se utiliza para definir la relación en el lado no propietario. En nuestra aplicación, el OrderEntity es el lado no propietario, y OrderItemEntity la tabla hija donde se originan muchas instancias desde una sola orden.
¿Cuáles son las recomendaciones para el uso de estas relaciones?
Al crear relaciones, es clave tener en cuenta el impacto en el desempeño de la aplicación. No siempre es necesario crear relaciones bidireccionales o añadir todas las posibles relaciones que se puedan modelar.
Simplificar consultas: Mediante consultas {query} o repositorios de Spring, se pueden derivar datos sin necesidad de establecer relaciones directas en todos los contextos.
Evitar sobrecarga: Solo se deben crear las relaciones que sean necesarias estrictamente para garantizar el rendimiento óptimo y la reducción de carga.
Crear relaciones en JPA es esencial para lograr una interacción efectiva entre entidades y bases de datos. Los conceptos discutidos, como el uso de anotaciones y claves compuestas, te posicionan mejor para desarrollar aplicaciones robustas que gestionan eficientemente los datos.
Sigue explorando y aplicando estos principios para afianzarte en el desarrollo backend utilizando JPA. ¡Tu maestría en estos conceptos solo puede mejorar y refinándose!
Tenia un error al ejecutar la aplicación porque el idCustomer en la clase Customer lo había definido como Integer y la creación de las tablas en la base de datos no podia hacer bien la creación de las llaves foraneas.
Elimine todas las tablas y luego hice la correción del campo y nuevamente ejecute la aplilcación para que me creará bien todas las tablas con sus llaves foraneas.
Jajaja justo leí tu comentario y me di cuenta que cometí el mismo error, gracias 👍
jajaja no me habia dado cuenta pero tenia el mismo error..
Gracias!
Tengo una duda acerca de la forma como se crearon estas relaciones:
Por que en la clase OrderItemEntity necesitamos idPizza si ya se esta creando con el atributo PizzaEntity
y lo mismo pero en la clase OrderEntity con el atributo idCustomer y el customerEntity
Se realiza de esta manera, porque como verás más adelante, cuando creemos una orden y/o una ítem de una orden no vamos a especificarle todo el objeto pizza o customer, sino que le enviaremos su clave primaria. Esto se usa así para no tener que usar objetos complejos al momento de crear u actualizar registros.
Estamos hablando de id's, si un cliente, hace una orden, entonces en esa orden solo habrá ese cliente. Puede pedir varios artículos, pero solo será en una orden. Al terminar la orden, puede volver a realizar otra, pero esa orden tendrá un nuevo id, y el cliente también, porque no se reusan clientes, a pesar de que puede tener el mismo nombre, el id cambia para ambos.
Se puede utilizar la anotación @Embeddable para la clase OrderItemId, y la anotación @EmbeddedId en la clase entity en la que se utiliza la llave compuesta. Por ejemplo: En la clase OrderItemEntity, incluirla de la siguiente manera:
Pero como un customer solo va a tener una Order, los customers pueden hacer varias órdenes, no entiendo porque lo hace asi.
Hola! están muy buenas las clases, gracias; me parece que podría tener un valor agregado al crearle clases test ya sea que se use JUnit o Mockito.
Por que no se usa la anotacion @EqualsAndHashCode de Lombok?
hola. como estas. podrías ayudarme en la conexión de la BD?!
A partir de acá tengo problemas.
A pesar de prácticamente “copiar y pegar” lo que hizo en el video, tengo este error
Caused by: java.sql.SQLException: Failed to add the foreign key constraint. Missing index for constraint 'FKakuoq412rnkuv4k0xsqeam5k0' in the referenced table 'pizza_order'
Buenas al ejecutar el archivo PlatziPizzeriaAplication del repositorio compartido por Git Hub; sale el siguiente error
Caused by: java.sql.SQLException: Failed to add the foreign key constraint. Missing index for constraint 'FKakuoq412rnkuv4k0xsqeam5k0' in the referenced table 'pizza_order', como podria solucionarlo. Gracias.
les paso el dato para que no les pase, le invertí unas horas para detectarlo, en la base de datos creaba los campos con camelCase ejem: idUser y a la hora de ejecutar las peticiones de la api, hibernate y su convencion de nombres convertian idUser a id_user entonces me generaba errores al hacer la request, la solución fué ya sea crear la base de datos desde hibernate o editar todos los campos de la base de datos ya creada, todos los que no cumplieran con la convención
Porque es que en OrderItem hay una clave conjunta?
No se supone que el ítem de una orden es único?
Es decir está bien que la IdOrder se repita porque una orden tiene más de una pizza pero el ítem debería ser único, como en las líneas de una factura.
No sé si entendí tu duda, pero yo lo veo de la siguiente manera, la tabla OrderItem representa la relación entre Order y Pizza, por lo que utilizar una clave primaria compuesta basada en ambos IDs le da identidad semántica a esa relación.
Aunque podríamos usar un ID artificial y dos FKs, la clave compuesta modela mejor el dominio, ya que garantiza que una misma pizza no pueda duplicarse dentro de la misma orden, obligando a manejar la cantidad mediante el atributo quantity en lugar de crear registros redundantes.
✅
En el siguiente codigo
name -> hace referencia al nombre de la columna en la tabla actual.
referencedColumnName -> hace referencia al nombre de la columna en la tabla que guarda a la entidad con la que estas haciendo la relacion.
ejemplo: Si tuvieras la Entidad Usuario y la entidad Direccion, y direccion tiene de id la columna "id", entonces en la entidad usuario al momento de hacer el join puedes hacer lo siguiente.
De esa manera estas diciendo que en tu entidad (que al final es una tabla) va a haber una columna llamada "direccion_id" que hace referencia a la columna "id" en la entidad Direccion.
porque ID pizza no tiene @ID si es clave foranea
@Id es solo para las llaves primarias
Fisicamente la tabla se creo on un Id SERIAL, esto esta bien?
¿Por qué quantity está como Double?
Porque explico en otro video que podrias pedir 1/2 pizza
Hola! Si uso @EmbeddedId, ¿como puedo hacer para acceder a un campo de la PK?. Ejemplo: si tengo entity "Candidato" con PK id_pais y dni, ¿como accedo a ese id_pais y a ese dni por separado?
A partir de acá tengo problemas.
A pesar de prácticamente "copiar y pegar" lo que hizo en el video, tengo este error
Error executing DDL "alter table moco add constraint FKhrjmy7mnjqfppn34uullm9335 foreign key (id_order) references pis (id_order)" via JDBC [Referencing column 'id_order' and referenced column 'id_order' in foreign key constraint 'FKhrjmy7mnjqfppn34uullm9335' are incompatible.]
Y las relaciones de las tablas no se generan.
Uso Maven y ya probé varias cosas como modificar el "Dialect"
Ya no se como continuar, este error me tiene bloqueado
Ya encontré la respuesta. Habian varias cosas que estaban mal. Por ejemplo:
Prestar atención a las anotaciones de las clases, una de ellas no tiene constructor.
Prestar atención a las anotaciones de los atributos, dos de ellas no tienen @GenerateValue()
Prestar atención a los tipos de las variables, Customer tiene Id del tipo String cuando el resto es Integer.
En las propiedades, la propiedad spring.jpa.hibernate.ddl-auto yo la tenia como "create" pero tiene que ir "update"
¿Porque todo esto? No lo se. Quiero usar UUID en los Ids y no puedo porque no se como cambiar los tipos de datos sin que me den errores al generar las tablas y columnas en la DB
Lograste como salir del problema?? estoy bloqueado, podrias ayudarme..
tengo una duda, cuando en el motor de base de datos mysql aplico el Reverse Enginner para ver el modelo de datos, aparece la relacion entre pizza y order_item de 1:n (uno a muchos), si se supone que deberia de ser 1:1, hice los pasos del video correctamente y aun asi me sale esa relacion
Si quieres cambiar el nombre de la llave foránea que se genera con un nombre aleatorio puedes agregar esta configuración.
Para cancelar la creación de las tablas y propiedades usando snake_case y que se creen como se definió en la clase modificar el archivo application.property