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
@JoinColumnindica 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 atributomappedByindica 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
@JoinColumnenCompanyBranchno tiene una propiedad que haga referenciaCompany, pero la tabla subyacente tiene una columna que sí, puede usarla@JoinTablepara 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 unnullen su columna FKey que hace referencia al padre.@JoinColumnpodría usarse en ambos lados de la relación. La pregunta era sobre el uso@JoinColumnen el@OneToManylado (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á algunasUPDATEdeclaraciones 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=...)Trooptiene una relación bidireccional de uno a muchos aSoldiertravés de la propiedad de la tropa. No es necesario (no debe) definir ningún mapeo físico en elmappedBylateral.Para asignar un ser bidireccional para muchos, con el lado de uno-a-muchos como el lado propietario , usted tiene que quitar el
mappedByelemento y establecer el muchos a uno@JoinColumncomoinsertableyupdatableen false. Esta solución no está optimizada y producirá algunasUPDATEdeclaraciones 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
@OneToManyanotación con@JoinColumn, entonces tiene una asociación unidireccional, como la que existe entre laPostentidad principal y el elemento secundarioPostCommenten 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
Postentidad definirá una@OneToManyasociación con laPostCommententidad secundaria :Asociación bidireccional uno a muchos
Si usa el
@OneToManycon elmappedByconjunto de atributos, tiene una asociación bidireccional. En nuestro caso, tanto laPostentidad tiene una colección dePostCommententidades secundarias como laPostCommententidad secundaria tiene una referencia a laPostentidad principal , como se ilustra en el siguiente diagrama:En la
PostCommententidad, lapostpropiedad de la entidad se asigna de la siguiente manera:En la
Postentidad, lacommentsasociación se asigna de la siguiente manera:El
mappedByatributo de la@OneToManyanotación hace referencia a lapostpropiedad en laPostCommententidad secundaria y, de esta manera, Hibernate sabe que la asociación bidireccional está controlada por el@ManyToOnelado, 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
addChildyremoveChild: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
@OneToManyno funciona muy bien , por lo que debe evitarla.Es mejor usar el bidireccional,
@OneToManyque 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
@JoinColumnno siempre tiene que estar relacionado con la ubicación de la información física, como sugiere esta respuesta. Se pueden combinar@JoinColumncon@OneToManyincluso 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
@JoinColumnque indica que esta entidad es la propietaria de la relación. En cambio, es la@ManyToOneanotación la que hace esto (en su ejemplo).Las anotaciones de relación como
@ManyToOne,@OneToManyy le@ManyToManydicen 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:
MappedByes 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.MappedBydetiene ese proceso en una dirección.Se
MappedBydice 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:
@JoinColumncrea una nueva columna de unión o renombra una existente; mientras que elMappedBypará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
MapppedByfunciona, considere el siguiente código. SiMappedByse 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/mappedByes más agradable porque solo usa las anotaciones del dominio de la entidad. El@oneToMany/@JoinColumntambié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