¿En qué caso utiliza la @JoinTable
anotación JPA ?
fuente
¿En qué caso utiliza la @JoinTable
anotación JPA ?
EDITAR 2017-04-29 : Como señalaron algunos de los comentaristas, el JoinTable
ejemplo no necesita el mappedBy
atributo de anotación. De hecho, las versiones recientes de Hibernate se niegan a iniciarse imprimiendo el siguiente error:
org.hibernate.AnnotationException:
Associations marked as mappedBy must not define database mappings
like @JoinTable or @JoinColumn
Supongamos que tiene una entidad llamada Project
y otra entidad nombrada Task
y cada proyecto puede tener muchas tareas.
Puede diseñar el esquema de la base de datos para este escenario de dos maneras.
La primera solución es crear una tabla llamada Project
y otra tabla llamada Task
y agregar una columna de clave externa a la tabla de tareas llamada project_id
:
Project Task
------- ----
id id
name name
project_id
De esta manera, será posible determinar el proyecto para cada fila en la tabla de tareas. Si usa este enfoque, en sus clases de entidad no necesitará una tabla de unión:
@Entity
public class Project {
@OneToMany(mappedBy = "project")
private Collection<Task> tasks;
}
@Entity
public class Task {
@ManyToOne
private Project project;
}
La otra solución es usar una tercera tabla, por ejemplo Project_Tasks
, y almacenar la relación entre proyectos y tareas en esa tabla:
Project Task Project_Tasks
------- ---- -------------
id id project_id
name name task_id
La Project_Tasks
tabla se llama "Unir tabla". Para implementar esta segunda solución en JPA, debe usar la @JoinTable
anotación. Por ejemplo, para implementar una asociación unidireccional de uno a muchos, podemos definir nuestras entidades como tales:
Project
entidad:
@Entity
public class Project {
@Id
@GeneratedValue
private Long pid;
private String name;
@JoinTable
@OneToMany
private List<Task> tasks;
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Task> getTasks() {
return tasks;
}
public void setTasks(List<Task> tasks) {
this.tasks = tasks;
}
}
Task
entidad:
@Entity
public class Task {
@Id
@GeneratedValue
private Long tid;
private String name;
public Long getTid() {
return tid;
}
public void setTid(Long tid) {
this.tid = tid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Esto creará la siguiente estructura de base de datos:
La @JoinTable
anotación también le permite personalizar varios aspectos de la tabla de unión. Por ejemplo, si hubiéramos anotado la tasks
propiedad de esta manera:
@JoinTable(
name = "MY_JT",
joinColumns = @JoinColumn(
name = "PROJ_ID",
referencedColumnName = "PID"
),
inverseJoinColumns = @JoinColumn(
name = "TASK_ID",
referencedColumnName = "TID"
)
)
@OneToMany
private List<Task> tasks;
La base de datos resultante se habría convertido en:
Finalmente, si desea crear un esquema para una asociación de muchos a muchos, el uso de una tabla de unión es la única solución disponible.
@JoinTable/@JoinColumn
puede ser anotada en el mismo campo conmappedBy
. Así que el ejemplo correcto debería ser mantener elmappedBy
enProject
, y mover el@JoinColumn
aTask.project
(o viceversa)Project_Tasks
necesita elname
deTask
, así, que se convierte en tres columnas:project_id
,task_id
,task_name
, cómo lograr esto?Caused by: org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn:
También es más limpio de usar
@JoinTable
cuando una entidad podría ser el niño en varias relaciones padre / hijo con diferentes tipos de padres. Para seguir con el ejemplo de Behrang, imagine que una Tarea puede ser hija de Proyecto, Persona, Departamento, Estudio y Proceso.¿Debe la
task
tabla tener 5nullable
campos de clave externa? Yo creo que no...fuente
Es la única solución para mapear una asociación ManyToMany: necesita una tabla de unión entre las dos tablas de entidades para mapear la asociación.
También se usa para asociaciones OneToMany (generalmente unidireccionales) cuando no desea agregar una clave foránea en la tabla del lado múltiple y así mantenerla independiente del lado uno.
Busque @JoinTable en la documentación de hibernación para obtener explicaciones y ejemplos.
fuente
Te permite manejar una relación de Muchos a Muchos. Ejemplo:
Join Table le permite crear una asignación utilizando:
creará una tabla:
fuente
@ManyToMany
asociacionesEn la mayoría de los casos, necesitará usar
@JoinTable
anotaciones para especificar la asignación de una relación de tabla de varios a varios:Entonces, suponiendo que tenga las siguientes tablas de base de datos:
En la
Post
entidad, mapearía esta relación, así:La
@JoinTable
anotación se utiliza para especificar el nombre de la tabla a través delname
atributo, así como la columna de clave externa que hace referencia a lapost
tabla (por ejemplo,joinColumns
) y la columna de clave externa en lapost_tag
tabla de enlaces que hace referencia a laTag
entidad a través delinverseJoinColumns
atributo.@OneToMany
Asociaciones unidireccionalesLas
@OneToMany
asociaciones unidireccionales , que carecen de@JoinColumn
mapeo, se comportan como relaciones de tabla de muchos a muchos, en lugar de uno a muchos.Entonces, suponiendo que tenga las siguientes asignaciones de entidades:
Hibernate asumirá el siguiente esquema de base de datos para la asignación de entidad anterior:
Como ya se explicó, el
@OneToMany
mapeo unidireccional de JPA se comporta como una asociación de muchos a muchos.Para personalizar la tabla de enlaces, también puede usar la
@JoinTable
anotación:Y ahora, se llamará a la tabla de enlaces
post_comment_ref
y las columnas de clave externa seránpost_id
, para lapost
tabla ypost_comment_id
, para lapost_comment
tabla.fuente