hibernate - onetomany - ¿A qué se hace referencia para utilizar el nombre de columna en JPA?
many to one jpa (5)
En JPA hay un atributo llamado referencedColumnName
que se puede configurar en @JoinColumn, @PrimaryKeyJoinColumn
cuál es la idea detrás de esta configuración, alguien puede dar un buen ejemplo de dónde se puede utilizar?
Citando API en referenciaColumnName :
El nombre de la columna a la que hace referencia esta columna de clave externa.
Predeterminado (solo se aplica si se está utilizando una sola columna de unión): el mismo nombre que la columna de la clave principal de la tabla a la que se hace referencia.
Q / A
¿Dónde se usaría esto?
Cuando hay una PK compuesta en la tabla a la que se hace referencia , debe especificar el nombre de columna al que hace referencia.
Está allí para especificar otra columna como la columna de ID predeterminada de la otra tabla, por ejemplo, considere lo siguiente
TableA
id int identity
tableb_key varchar
TableB
id int identity
key varchar unique
// in class for TableA
@JoinColumn(name="tableb_key", referencedColumnName="key")
La propiedad "referencedColumnName" es el nombre de la columna de la tabla que está haciendo referencia con la columna que está anotando. O de manera breve: es la columna a la que se hace referencia en la tabla de destino. Imagine algo como esto: automóviles y personas. Una persona puede tener muchos automóviles, pero un automóvil pertenece solo a una persona (lo siento, no me gusta que nadie más conduzca mi automóvil).
Persona de la mesa
nombre char (64) clave principal
edad intCoche de tabla
car_registration char (32) clave principal
car_brand (char 64)
car_model (char64)
owner_name char (64) foreign key references Persona (nombre)
Cuando implemente clases tendrá algo como
class Person{
...
}
class Car{
...
@ManyToOne
@JoinColumn(columnName="owner_name", referencedColumnName="name")
private Person owner;
}
Espero que esto ayude.
Para un uso de ejemplo de JPA 2.x para el caso general de dos tablas, con una @OneToMany
unidireccional @OneToMany
consulte https://en.wikibooks.org/wiki/Java_Persistence/OneToMany#Example_of_a_JPA_2.x_unidirectional_OneToMany_relationship_annotations
Captura de pantalla de este artículo WikiBooks JPA: Ejemplo de una base de datos de relaciones OneToMany unidireccional JPA 2.x.
-
name
puntos de atributo a la columna que contiene la asociación, es decir, el nombre de la columna de la clave externa -
referencedColumnName
atributoreferencedColumnName
apunta a la columna relacionada en la entidad asociada / referenciada, es decir, el nombre de columna de la clave primaria
No es necesario que rellene el Address
columna referencedColumnName
si la entidad a la que se hace referencia tiene una sola columna como PK, porque no hay duda a qué columna hace referencia (es decir, el ID de columna única de Address
).
@ManyToOne
@JoinColumn(name="ADDR_ID")
public Address getAddress() { return address; }
Sin embargo, si la entidad a la que se hace referencia tiene PK que abarca varias columnas, el orden en el que se especifican @JoinColumn
anotaciones @JoinColumn
tiene significado. Puede funcionar sin el nombre de columna referencedColumnName
especificado, pero eso es solo por suerte. Entonces deberías mapearlo así:
@ManyToOne
@JoinColumns({
@JoinColumn(name="ADDR_ID", referencedColumnName="ID"),
@JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")
})
public Address getAddress() { return address; }
o en el caso de ManyToMany
:
@ManyToMany
@JoinTable(
name="CUST_ADDR",
joinColumns=
@JoinColumn(name="CUST_ID"),
inverseJoinColumns={
@JoinColumn(name="ADDR_ID", referencedColumnName="ID"),
@JoinColumn(name="ADDR_ZIP", referencedColumnName="ZIP")
}
)
Ejemplo de vida real
Dos consultas generadas por Hibernate de la misma asignación de tabla de combinación, ambas sin columna de referencia especificada. Solo se modificó el orden de @JoinColumn
anotaciones @JoinColumn
.
/* load collection Client.emails */
select
emails0_.id_client as id1_18_1_,
emails0_.rev as rev18_1_,
emails0_.id_email as id3_1_,
email1_.id_email as id1_6_0_
from client_email emails0_
inner join email email1_ on emails0_.id_email=email1_.id_email
where emails0_.id_client=''2'' and
emails0_.rev=''18''
/* load collection Client.emails */
select
emails0_.rev as rev18_1_,
emails0_.id_client as id2_18_1_,
emails0_.id_email as id3_1_,
email1_.id_email as id1_6_0_
from client_email emails0_
inner join email email1_ on emails0_.id_email=email1_.id_email
where emails0_.rev=''2'' and
emails0_.id_client=''18''
Estamos consultando una tabla de unión para obtener los correos electrónicos del cliente. El {2, 18}
es una identificación compuesta de Cliente. El orden de los nombres de las columnas está determinado por su orden de anotaciones @JoinColumn
. El orden de ambos enteros es siempre el mismo, probablemente ordenado por hibernación y es por eso que se requiere una alineación adecuada con las columnas de la tabla de unión y no podemos o debemos confiar en el orden de mapeo.
Lo interesante es que el orden de los enteros no coincide con el orden en el que están mapeados en la entidad, en ese caso esperaría {18, 2}
. Así que parece que Hibernate está ordenando los nombres de las columnas antes de usarlas en la consulta. Si esto es cierto y usted ordenaría su @JoinColumn
de la misma manera que no necesitaría referencedColumnName
, pero digo esto solo para ilustración.
Los atributos apropiadamente rellenos referencedColumnName
dan como resultado exactamente la misma consulta sin la ambigüedad, en mi caso la segunda consulta ( rev = 2
, id_client = 18
).