Cuál es la diferencia entre:
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY)
@JoinColumn(name = "companyIdRef", referencedColumnName = "companyId")
private List<Branch> branches;
...
}
y
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY, mappedBy = "companyIdRef")
private List<Branch> branches;
...
}
Respuestas:
La anotación
@JoinColumn
indica que esta entidad es la propietaria de la relación (es decir: la tabla correspondiente tiene una columna con una clave foránea para la tabla referenciada), mientras que el atributomappedBy
indica que la entidad en este lado es el inverso de la relación, y el propietario reside en la "otra" entidad. Esto también significa que puede acceder a la otra tabla desde la clase que ha anotado con "mappedBy" (relación totalmente bidireccional).En particular, para el código en la pregunta, las anotaciones correctas se verían así:
fuente
@JoinColumn
enCompany
Branch
no tiene una propiedad que haga referenciaCompany
, pero la tabla subyacente tiene una columna que sí, puede usarla@JoinTable
para asignarla. Esta es una situación inusual, porque normalmente mapearía la columna en el objeto que corresponde a su tabla, pero puede suceder y es perfectamente legítimo.@OneToOne
, las filas secundarias se actualizan con unnull
en su columna FKey que hace referencia al padre.@JoinColumn
podría usarse en ambos lados de la relación. La pregunta era sobre el uso@JoinColumn
en el@OneToMany
lado (caso raro). Y el punto aquí está en la duplicación de información física (nombre de columna) junto con una consulta SQL no optimizada que producirá algunasUPDATE
declaraciones adicionales .Según la documentación :
Dado que muchos a uno son (casi) siempre el lado propietario de una relación bidireccional en la especificación JPA, la asociación uno a muchos está anotada por
@OneToMany(mappedBy=...)
Troop
tiene una relación bidireccional de uno a muchos aSoldier
través de la propiedad de la tropa. No es necesario (no debe) definir ningún mapeo físico en elmappedBy
lateral.Para asignar un ser bidireccional para muchos, con el lado de uno-a-muchos como el lado propietario , usted tiene que quitar el
mappedBy
elemento y establecer el muchos a uno@JoinColumn
comoinsertable
yupdatable
en false. Esta solución no está optimizada y producirá algunasUPDATE
declaraciones adicionales .fuente
mappedBy="troop"
refiere a qué campo?mappedBy="troop"
refiere a la tropa de propiedad en la clase Soldado. En el código anterior, la propiedad no es visible porque aquí Mykhaylo la omitió, pero puede deducir su existencia mediante el getter getTroop (). Comprueba la respuesta de Óscar López , está muy claro y entenderás el punto.Asociación unidireccional de uno a muchos
Como expliqué en este artículo , si usa la
@OneToMany
anotación con@JoinColumn
, entonces tiene una asociación unidireccional, como la que existe entre laPost
entidad principal y el elemento secundarioPostComment
en el siguiente diagrama:Cuando se usa una asociación unidireccional de uno a muchos, solo el lado padre mapea la asociación.
En este ejemplo, solo la
Post
entidad definirá una@OneToMany
asociación con laPostComment
entidad secundaria :Asociación bidireccional uno a muchos
Si usa el
@OneToMany
con elmappedBy
conjunto de atributos, tiene una asociación bidireccional. En nuestro caso, tanto laPost
entidad tiene una colección dePostComment
entidades secundarias como laPostComment
entidad secundaria tiene una referencia a laPost
entidad principal , como se ilustra en el siguiente diagrama:En la
PostComment
entidad, lapost
propiedad de la entidad se asigna de la siguiente manera:En la
Post
entidad, lacomments
asociación se asigna de la siguiente manera:El
mappedBy
atributo de la@OneToMany
anotación hace referencia a lapost
propiedad en laPostComment
entidad secundaria y, de esta manera, Hibernate sabe que la asociación bidireccional está controlada por el@ManyToOne
lado, que se encarga de administrar el valor de la columna Clave externa en la que se basa esta relación de tabla.Para una asociación bidireccional, también debe tener dos métodos de utilidad, como
addChild
yremoveChild
:Estos dos métodos aseguran que ambos lados de la asociación bidireccional no estén sincronizados. Sin sincronizar ambos extremos, Hibernate no garantiza que los cambios de estado de asociación se propaguen a la base de datos.
¿Cuál elegir?
La asociación unidireccional
@OneToMany
no funciona muy bien , por lo que debe evitarla.Es mejor usar el bidireccional,
@OneToMany
que es más eficiente .fuente
La anotación mappedBy idealmente siempre debe usarse en el lado principal (clase de empresa) de la relación bidireccional, en este caso debe estar en la clase de empresa que apunta a la variable miembro 'empresa' de la clase secundaria (clase de sucursal)
La anotación @JoinColumn se usa para especificar una columna asignada para unirse a una asociación de entidad, esta anotación se puede usar en cualquier clase (padre o hijo), pero idealmente se debe usar solo en un lado (en la clase padre o en la clase hija no en ambos) aquí, en este caso, lo usé en el lado secundario (clase Branch) de la relación bidireccional que indica la clave foránea en la clase Branch.
A continuación se muestra el ejemplo de trabajo:
clase matriz, empresa
clase infantil, rama
fuente
Solo me gustaría agregar que
@JoinColumn
no siempre tiene que estar relacionado con la ubicación de la información física, como sugiere esta respuesta. Se pueden combinar@JoinColumn
con@OneToMany
incluso si la tabla primaria no tiene datos de la tabla apuntando a la tabla secundaria.Cómo definir la relación unidireccional OneToMany en JPA
Unidireccional OneToMany, No Inverse ManyToOne, No Join Table
Sin
JPA 2.x+
embargo, parece que solo está disponible en . Es útil para situaciones en las que desea que la clase secundaria solo contenga el ID del padre, no una referencia completa.fuente
No estoy de acuerdo con la respuesta aceptada aquí por Óscar López. ¡Esa respuesta es inexacta!
NO es lo
@JoinColumn
que indica que esta entidad es la propietaria de la relación. En cambio, es la@ManyToOne
anotación la que hace esto (en su ejemplo).Las anotaciones de relación como
@ManyToOne
,@OneToMany
y le@ManyToMany
dicen a JPA / Hibernate que cree un mapeo. Por defecto, esto se realiza a través de una tabla de unión separada.@JoinColumn
MappedBy
Recuerde:
MappedBy
es una propiedad de las anotaciones de relación cuyo propósito es generar un mecanismo para relacionar dos entidades que por defecto lo hacen al crear una tabla de unión.MappedBy
detiene ese proceso en una dirección.Se
MappedBy
dice que la entidad que no utiliza es la propietaria de la relación porque la mecánica de la asignación se dicta dentro de su clase mediante el uso de una de las tres anotaciones de asignación en el campo de clave externa. Esto no solo especifica la naturaleza de la asignación, sino que también indica la creación de una tabla de unión. Además, la opción de suprimir la tabla de unión también existe aplicando la anotación @JoinColumn sobre la clave externa que la mantiene dentro de la tabla de la entidad propietaria.En resumen:
@JoinColumn
crea una nueva columna de unión o renombra una existente; mientras que elMappedBy
parámetro funciona en colaboración con las anotaciones de relación de la otra clase (secundaria) para crear un mapeo a través de una tabla de unión o creando una columna de clave externa en la tabla asociada de la entidad propietaria.Para ilustrar cómo
MapppedBy
funciona, considere el siguiente código. SiMappedBy
se eliminara el parámetro, ¡Hibernate crearía DOS tablas de unión! ¿Por qué? Debido a que existe una simetría en las relaciones de muchos a muchos, Hibernate no tiene fundamentos para seleccionar una dirección sobre la otra.Por lo tanto
MappedBy
, solemos decirle a Hibernate que hemos elegido la otra entidad para dictar el mapeo de la relación entre las dos entidades.Agregar @JoinColumn (name = "driverID") en la clase de propietario (ver más abajo), evitará la creación de una tabla de unión y, en su lugar, creará una columna de clave externa driverID en la tabla Cars para construir una asignación:
fuente
JPA es una API en capas, los diferentes niveles tienen sus propias anotaciones. El nivel más alto es el (1) nivel de entidad que describe las clases persistentes, entonces tiene el (2) nivel de base de datos relacional que supone que las entidades se asignan a una base de datos relacional y (3) el modelo de Java.
Nivel 1 anotaciones:
@Entity
,@Id
,@OneToOne
,@OneToMany
,@ManyToOne
,@ManyToMany
. Puede introducir persistencia en su aplicación utilizando solo estas anotaciones de alto nivel. Pero luego debe crear su base de datos de acuerdo con los supuestos que hace JPA. Estas anotaciones especifican el modelo de entidad / relación.Nivel 2 anotaciones:
@Table
,@Column
,@JoinColumn
, ... influir en la asignación de entidades / propiedades a las mesas de bases de datos relacionales / columnas si no está satisfecho con los valores predeterminados de la APP o si necesita asignar a una base de datos existente. Estas anotaciones pueden verse como anotaciones de implementación, especifican cómo se debe hacer la asignación.En mi opinión, es mejor atenerse lo más posible a las anotaciones de alto nivel y luego introducir las anotaciones de nivel inferior según sea necesario.
Para responder las preguntas: el
@OneToMany
/mappedBy
es más agradable porque solo usa las anotaciones del dominio de la entidad. El@oneToMany
/@JoinColumn
también está bien, pero utiliza una anotación de implementación donde esto no es estrictamente necesario.fuente
Déjame hacerlo simple.
Puede usar @JoinColumn en ambos lados, independientemente de la asignación.
Dividamos esto en tres casos.
1) Mapeo unidireccional de sucursal a empresa.
2) Mapeo bidireccional de empresa a sucursal.
3) Solo mapeo unidireccional de empresa a sucursal.
Por lo tanto, cualquier caso de uso se incluirá en estas tres categorías. Déjame explicarte cómo usar @JoinColumn y mappedBy .
1) Mapeo unidireccional de sucursal a empresa.
Use JoinColumn en la tabla Branch.
2) Mapeo bidireccional de empresa a sucursal.
Use mappedBy en la tabla de la compañía como se describe en la respuesta de @Mykhaylo Adamovych.
3) Mapeo unidireccional de empresa a sucursal.
Solo use @JoinColumn en la tabla Compañía.
Esto dice que en función de la asignación de clave externa "courseId" en la tabla de sucursales, obtener una lista de todas las sucursales. NOTA: en este caso, no puede obtener una empresa de una sucursal, solo existe una asignación unidireccional de una empresa a otra.
fuente