mapeo - Hibernate/JPA ManyToOne versus OneToMany
onetomany hibernate ejemplo (2)
Estoy leyendo actualmente la documentación de Hibernate con respecto a las asociaciones de entidades y encuentro una pequeña dificultad para descubrir algunas cosas. Tiene que ver en esencia con la diferencia entre las asociaciones ManyToOne
y OneToMany
. Aunque los he usado en proyectos reales, no puedo comprender completamente la diferencia entre ellos. A mi entender, si una tabla / una entidad tiene una asociación ManyToOne
con otra, entonces la asociación debe ser desde el otro lado OneToMany
. Entonces, ¿cómo deberíamos decidir cuál elegir en función de un caso específico y cómo afecta la base de datos / consultas / resultados? ¿Hay en todas partes un buen ejemplo?
PD: reconozco que sería útil debido a su relevancia para la pregunta, si alguien pudiera además explicar cuál es el punto del propietario de la asociación y la diferencia entre la asociación Bidireccional y Unidireccional.
Además, tener @ManytoOne
lado de @ManytoOne
como propietario requerirá solo n + 1 consultas mientras se guardan las asociaciones. Donde n es el número de asociaciones (muchos lados).
Mientras que tener @OneToMany
como propietario, al insertar la entidad padre (un lado) con asociaciones (muchas caras) resultaría en 2 * N + 1 consultas. En el que una consulta sería para insertar la asociación y otra consulta sería para actualizar la clave externa en la entidad asociada.
Supongamos que tiene una orden y una línea de pedido. Puede optar por tener OneToMany unidireccional entre Order y OrderLine (Order tendría una colección de OrderLines). O puede optar por tener una asociación ManyToOne entre OrderLine y Order (OrderLine tendría una referencia a su orden). O puede elegir tener ambos, en cuyo caso la asociación se convierte en una asociación OneToMany / ManyToOne bidireccional.
La solución que elija depende principalmente de la situación y del nivel de acoplamiento entre las entidades. Por ejemplo, si un usuario, una empresa o un proveedor tienen muchas direcciones, sería lógico tener una dirección unidireccional entre cada una de ellas y la Dirección, y la Dirección no conocería a su propietario.
Supongamos que tiene un Usuario y un Mensaje, donde un usuario puede tener miles de mensajes, podría tener sentido modelarlo solo como un mensaje de ManyToOne a Usuario, porque raramente solicitará todos los mensajes de un usuario de todos modos. La asociación podría hacerse bidireccional solo para ayudar con consultas, ya que las consultas JPQL se unen entre entidades navegando a través de sus asociaciones.
En una asociación bidireccional, podría encontrarse en una situación en la que el gráfico de objetos es inconsistente. Por ejemplo, el pedido A tendría un conjunto vacío de líneas de pedido, pero algunas líneas de pedido tendrían una referencia al pedido A. JPA impone tener siempre un lado de la asociación como el lado propietario y el otro lado el lado inverso. El lado inverso es ignorado por JPA. El lado del dueño es el lado que decide qué relación existe. En una asociación bidireccional OneToMany, el lado del propietario debe ser el lado de muchos. Entonces, en el ejemplo anterior, el lado del propietario sería OrderLine, y JPA persistiría en la asociación entre las líneas y el orden A, ya que las líneas tienen una referencia a A.
Tal asociación se mapearía así:
en orden :
@OneToMany(mappedBy = "parentOrder") // mappedBy indicates that this side is the
// inverse side, and that the mapping is defined by the attribute parentOrder
// at the other side of the association.
private Set<OrderLine> lines;
en OrderLine:
@ManyToOne
private Order parentOrder;