JPA: ¿diferencia entre @JoinColumn y @PrimaryKeyJoinColumn?

82

¿Cuál es la diferencia exacta entre @JoinColumny @PrimaryKeyJoinColumn?

Se usa @JoinColumnpara columnas que forman parte de una clave externa. Una columna típica podría verse así (por ejemplo, en una tabla de combinación con atributos adicionales):

@ManyToOne
@JoinColumn(name = "...")
private OtherClass oc;

¿Qué sucede si promociono la columna para que sea un / el PK también (también conocido como relación de identificación)? Como la columna ahora es PK, debo etiquetarla con @Id:

@Id
@ManyToOne
@JoinColumn(name = "...")
private OtherClass oc;

Ahora la pregunta es:

¿Son @Id+ @JoinColumnlo mismo que solo @PrimaryKeyJoinColumn?:

@ManyToOne
@PrimaryKeyJoinColumn(name = "...")
private OtherClass oc;

Si no es así, ¿para qué @PrimaryKeyJoinColumnsirve?

Kawu
fuente

Respuestas:

54

¿Qué sucede si promociono la columna para que sea un / el PK también (también conocido como relación de identificación)? Como la columna ahora es el PK, debo etiquetarla con @Id (...).

Este soporte mejorado de identificadores derivados es en realidad parte de las novedades en JPA 2.0 (consulte la sección 2.4.1 Claves primarias correspondientes a identidades derivadas en la especificación JPA 2.0), JPA 1.0 no permite Iden un OneToOneo ManyToOne. Con JPA 1.0, tendría que usar PrimaryKeyJoinColumny también definir una Basic Idasignación para la columna de clave externa.

Ahora la pregunta es: ¿@Id + @JoinColumn es lo mismo que @PrimaryKeyJoinColumn?

Puede obtener un resultado similar, pero usando un Idon OneToOneo ManyToOnees mucho más simple y es la forma preferida de mapear identificadores derivados con JPA 2.0. PrimaryKeyJoinColumnaún podría usarse en una estrategia de herencia JOINED . Debajo de la sección relevante de la especificación JPA 2.0:

11.1.40 Anotación de PrimaryKeyJoinColumn

La PrimaryKeyJoinColumnanotación especifica una columna de clave principal que se utiliza como clave externa para unirse a otra tabla.

La PrimaryKeyJoinColumnanotación se utiliza para unir la tabla principal de una subclase de entidad en la JOINED estrategia de mapeo a la tabla principal de su superclase; se utiliza dentro de una SecondaryTableanotación para unir una tabla secundaria a una tabla principal; y se puede utilizar en un OneToOne mapeo en el que la clave primaria de la entidad de referencia se utiliza como clave foránea para la entidad de referencia [108] .

...

Si no PrimaryKeyJoinColumn se especifica ninguna anotación para una subclase en la estrategia de mapeo JOINED, se asume que las columnas de clave externa tienen los mismos nombres que las columnas de clave primaria de la tabla primaria de la superclase.

...

Ejemplo: subclase Customer y ValuedCustomer

@Entity
@Table(name="CUST")
@Inheritance(strategy=JOINED)
@DiscriminatorValue("CUST")
public class Customer { ... }

@Entity
@Table(name="VCUST")
@DiscriminatorValue("VCUST")
@PrimaryKeyJoinColumn(name="CUST_ID")
public class ValuedCustomer extends Customer { ... }

[108] Los mecanismos de identificación derivados descritos en la sección 2.4.1.1 ahora son preferibles en PrimaryKeyJoinColumnel caso de mapeo OneToOne.

Ver también


Esta fuente http://weblogs.java.net/blog/felipegaucho/archive/2009/10/24/jpa-join-table-additional-state afirma que el uso de @ManyToOne y @Id funciona con JPA 1.x. ¿Quién tiene razón ahora?

El autor está utilizando una versión previa al lanzamiento compatible con JPA 2.0 de EclipseLink (versión 2.0.0-M7 en el momento del artículo) para escribir un artículo sobre JPA 1.0 (!). Este artículo es engañoso, el autor está usando algo que NO es parte de JPA 1.0.

Para que conste, se ha agregado compatibilidad con Idon OneToOney ManyToOneen EclipseLink 1.1 (consulte este mensaje de James Sutherland , comitter de EclipseLink y colaborador principal del libro wiki de Java Persistence ). Pero déjeme insistir, esto NO es parte de JPA 1.0.

Pascal Thivent
fuente
Esta fuente weblogs.java.net/blog/felipegaucho/archive/2009/10/24/… establece que el uso de @ManyToOne y @Id funciona con JPA 1.x. ¿Quién tiene razón ahora?
Kawu
OKAY. Gracias por aclarar eso. ¿Tengo razón en que el mal ejemplo al que se hace referencia usa @IdClass incorrectamente? ¿No deberían colocarse las anotaciones @Id en las columnas separadas (redundantes / duplicadas) en la clase de entidad para que sean correctas? (aunque sé que ya no se recomienda usar @IdClass)
Kawu
Quiero decir, debería haber dos propiedades en la clase: @Id @Column private String Institution; y el concurso privado de cadenas @Id @Column; solo para especificar el PK, ¿verdad?
Kawu
@Kawu Lo siento, pero honestamente, es demasiado difícil discutir esto en un pequeño cuadro de comentarios. Ni siquiera estoy seguro de haber entendido de qué estás hablando. Si tiene otra pregunta específica, le sugiero que elija una implementación de JPA y experimente un poco o que publique una nueva pregunta con un ejemplo completo (y la versión de JPA). Esto facilitaría mucho las cosas.
Pascal Thivent
37

Normalmente diferencio estos dos a través de este diagrama:

Utilizar PrimaryKeyJoinColumn

ingrese la descripción de la imagen aquí

Utilizar JoinColumn

ingrese la descripción de la imagen aquí

Sam YC
fuente
2
@yusher, PrimaryKeyJoinColumnuse el mismo valor de clave principal para unir dos tablas, y JoinColumnla clave principal de la tabla principal se convertirá en clave externa en otra tabla.
Sam YC
2

Sé que esta es una publicación antigua, pero un buen momento para usarla PrimaryKeyColumnsería si quisiera una relación unidireccional o si tuviera varias tablas que compartan la misma identificación.

En general, esta es una mala idea y sería mejor usar relaciones de clave externa con JoinColumn.

Habiendo dicho eso, si está trabajando en una base de datos más antigua que usaba un sistema como este, sería un buen momento para usarlo.

Philip Read
fuente