En la sección de ejemplo de la @OneToMany
referencia de anotación JPA :
Ejemplo 1-59 @OneToMany - Clase de cliente con genéricos
@Entity
public class Customer implements Serializable {
...
@OneToMany(cascade=ALL, mappedBy="customer")
public Set<Order> getOrders() {
return orders;
}
...
}
Ejemplo 1-60 @ManyToOne - Clase de pedido con genéricos
@Entity
public class Order implements Serializable {
...
@ManyToOne
@JoinColumn(name="CUST_ID", nullable=false)
public Customer getCustomer() {
return customer;
}
...
}
Me parece que la Customer
entidad es la propietaria de la asociación. Sin embargo, en la explicación del mappedBy
atributo en el mismo documento, está escrito que:
si la relación es bidireccional, establezca el elemento mappedBy en el lado inverso (no propietario) de la asociación con el nombre del campo o propiedad que posee la relación como muestra el Ejemplo 1-60.
Sin embargo, si no me equivoco, parece que en el ejemplo, en mappedBy
realidad se especifica en el lado propietario de la asociación, en lugar del lado no propietario.
Entonces mi pregunta es básicamente:
En una asociación bidireccional (uno a muchos / muchos a uno), ¿cuál de las entidades es el propietario? ¿Cómo podemos designar a One side como el propietario? ¿Cómo podemos designar al lado Muchos como el propietario?
¿Qué se entiende por "el lado inverso de la asociación"? ¿Cómo podemos designar el lado uno como el inverso? ¿Cómo podemos designar el lado Muchos como el inverso?
Respuestas:
Para entender esto, debes dar un paso atrás. En OO, el cliente posee los pedidos (los pedidos son una lista en el objeto del cliente). No puede haber un pedido sin un cliente. Entonces el cliente parece ser el dueño de los pedidos.
Pero en el mundo SQL, un elemento contendrá un puntero al otro. Como hay 1 cliente para N pedidos, cada pedido contiene una clave externa para el cliente al que pertenece. Esta es la "conexión" y esto significa que el orden "posee" (o literalmente contiene) la conexión (información). Esto es exactamente lo contrario del mundo OO / modelo.
Esto puede ayudar a entender:
El lado inverso es el "propietario" OO del objeto, en este caso el cliente. El cliente no tiene columnas en la tabla para almacenar los pedidos, por lo que debe indicarle en qué lugar de la tabla de pedidos puede guardar estos datos (lo que ocurre a través de
mappedBy
).Otro ejemplo común son los árboles con nodos que pueden ser padres e hijos. En este caso, los dos campos se usan en una clase:
Esto explica para los trabajos de diseño muchos a uno de "clave externa". Hay un segundo enfoque que utiliza otra tabla para mantener las relaciones. Eso significa que, para nuestro primer ejemplo, tiene tres tablas: la que tiene clientes, la que tiene pedidos y una tabla de dos columnas con pares de claves principales (customerPK, orderPK).
Este enfoque es más flexible que el anterior (puede manejar fácilmente uno a uno, muchos a uno, uno a muchos e incluso muchos a muchos). El precio es que
Es por eso que rara vez recomiendo este enfoque.
fuente
@Parent
o@Child
anotación en lugar de "Xtoy" a estado de conexión lo que los medios (en lugar de la forma en que se implementa )Increíblemente, en 3 años nadie ha respondido a su excelente pregunta con ejemplos de ambas formas de mapear la relación.
Como han mencionado otros, el lado "propietario" contiene el puntero (clave externa) en la base de datos. Puede designar a cualquier lado como propietario, sin embargo, si designa al lado Uno como propietario, la relación no será bidireccional (el lado inverso "muchos" no tendrá conocimiento de su "propietario"). Esto puede ser deseable para encapsulación / acoplamiento suelto:
La única solución de mapeo bidireccional es que el lado "muchos" posea su puntero al "uno" y use el atributo "mappedBy" @OneToMany. Sin el atributo "mappedBy", Hibernate esperará una doble asignación (la base de datos tendría tanto la columna de unión como la tabla de unión, que es redundante (generalmente no deseable)).
fuente
La entidad que tiene la tabla con clave foránea en la base de datos es la entidad propietaria y la otra tabla, señalada, es la entidad inversa.
fuente
Reglas simples de relaciones bidireccionales:
1.Para las relaciones bidireccionales de muchos a uno, el lado múltiple es siempre el lado propietario de la relación. Ejemplo: 1 habitación tiene muchas personas (una persona pertenece a una sola habitación) -> el lado propietario es la persona
2.Para las relaciones bidireccionales uno a uno, el lado propietario corresponde al lado que contiene la clave foránea correspondiente.
3.Para las relaciones bidireccionales de muchos a muchos, cualquier lado puede ser el lado propietario.
La esperanza puede ayudarte.
fuente
Para dos clases de entidad Cliente y Pedido, hibernate creará dos tablas.
Posibles casos:
mappedBy no se usa en Customer.java y Order.java Class entonces->
En el lado del cliente, se creará una nueva tabla [name = CUSTOMER_ORDER] que mantendrá la asignación de CUSTOMER_ID y ORDER_ID. Estas son las claves principales de las tablas de clientes y pedidos. En el lado de la orden, se requiere una columna adicional para guardar la asignación de registro Customer_ID correspondiente.
mappedBy se usa en Customer.java [Como se indica en la declaración del problema] Ahora no se crea la tabla adicional [CUSTOMER_ORDER]. Solo una columna en la tabla de pedidos
mappedby se usa en Order.java. Ahora hibernate creará una tabla adicional. [name = CUSTOMER_ORDER] La tabla de pedidos no tendrá una columna adicional [Customer_ID] para la asignación.
Cualquier lado puede convertirse en propietario de la relación. Pero es mejor elegir el lado xxxToOne.
Efecto de codificación -> Solo el lado propietario de la entidad puede cambiar el estado de la relación. En el ejemplo a continuación, la clase BoyFriend es propietaria de la relación. incluso si Girlfriend quiere separarse, no puede.
fuente
Relaciones de tabla versus relaciones de entidad
En un sistema de base de datos relacional, solo puede haber tres tipos de relaciones de tabla:
Entonces, una
one-to-many
relación de tabla tiene el siguiente aspecto:Tenga en cuenta que la relación se basa en la columna Clave externa (por ejemplo,
post_id
) en la tabla secundaria.Entonces, hay una sola fuente de verdad cuando se trata de administrar una
one-to-many
relación de tabla.Ahora, si toma una relación de entidad bidireccional que se asigna en la
one-to-many
relación de tabla que vimos anteriormente:Si observa el diagrama anterior, puede ver que hay dos formas de gestionar esta relación.
En la
Post
entidad, tiene lacomments
colección:Y, en el
PostComment
, lapost
asociación se asigna de la siguiente manera:Entonces, tiene dos lados que pueden cambiar la asociación de la entidad:
comments
colección secundaria, sepost_comment
debe asociar una nueva fila con lapost
entidad principal a través de supost_id
columna.post
propiedad de laPostComment
entidad, lapost_id
columna también debe actualizarse.Debido a que hay dos formas de representar la columna Clave externa, debe definir cuál es la fuente de la verdad cuando se trata de traducir el cambio de estado de asociación en su modificación de valor de columna de clave externa equivalente.
MappedBy (también conocido como el lado inverso)
El
mappedBy
atributo indica que el@ManyToOne
lado está a cargo de administrar la columna Clave externa, y que la colección se usa solo para recuperar las entidades secundarias y en cascada los cambios de estado de la entidad primaria a los elementos secundarios (por ejemplo, eliminar el elemento primario también debería eliminar las entidades secundarias).Sincronice ambos lados de una asociación bidireccional
Ahora, incluso si definió el
mappedBy
atributo y la@ManyToOne
asociación del lado secundario maneja la columna Clave externa, aún necesita sincronizar ambos lados de la asociación bidireccional.La mejor manera de hacerlo es agregar estos dos métodos de utilidad:
Los métodos
addComment
yremoveComment
aseguran que ambos lados estén sincronizados. Entonces, si agregamos una entidad secundaria, la entidad secundaria debe apuntar al elemento primario y la entidad principal debe tener el elemento secundario contenido en la colección secundaria.fuente