Dans quel cas utilisez-vous l'annotation JPA @JoinTable
_?
EDIT 2017-04-29 : Comme l'ont souligné certains des commentateurs, l'exemple JoinTable
n'a pas besoin de mappedBy
attribut d'annotation. En fait, les versions récentes d'Hibernate refusent de démarrer en imprimant l'erreur suivante:
org.hibernate.AnnotationException:
Associations marked as mappedBy must not define database mappings
like @JoinTable or @JoinColumn
Supposons que vous avez une entité nommée Project
et une autre entité nommée Task
et que chaque projet peut avoir de nombreuses tâches.
Vous pouvez concevoir le schéma de base de données pour ce scénario de deux manières.
La première solution consiste à créer une table nommée Project
et une autre table nommée Task
et à ajouter une colonne de clé étrangère à la table de tâches nommée project_id
:
Project Task
------- ----
id id
name name
project_id
De cette façon, il sera possible de déterminer le projet pour chaque ligne de la table des tâches. Si vous utilisez cette approche, dans vos classes d'entité, vous n'aurez pas besoin d'une table de jointure:
@Entity
public class Project {
@OneToMany(mappedBy = "project")
private Collection<Task> tasks;
}
@Entity
public class Task {
@ManyToOne
private Project project;
}
L’autre solution consiste à utiliser une troisième table, par exemple Project_Tasks
, et stockez la relation entre les projets et les tâches dans cette table:
Project Task Project_Tasks
------- ---- -------------
id id project_id
name name task_id
La table Project_Tasks
s'appelle une "table de jointure". Pour implémenter cette deuxième solution dans JPA, vous devez utiliser l'annotation @JoinTable
. Par exemple, afin de mettre en place une association un-à-plusieurs unidirectionnelle, nous pouvons définir nos entités comme telles:
Project
entité:
@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
entité:
@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;
}
}
Cela créera la structure de base de données suivante:
L'annotation @JoinTable
vous permet également de personnaliser divers aspects de la table de jointure. Par exemple, avions-nous annoté la propriété tasks
comme ceci:
@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 données résultante serait devenue:
Enfin, si vous souhaitez créer un schéma pour une association plusieurs à plusieurs, l'utilisation d'une table de jointure est la seule solution disponible.
C'est la seule solution pour mapper une association ManyToMany: vous avez besoin d'une table de jointure entre les tables de deux entités pour mapper l'association.
Il est également utilisé pour les associations OneToMany (généralement unidirectionnelles) lorsque vous ne souhaitez pas ajouter une clé étrangère dans la table du côté multiple et la conserver ainsi indépendante du premier côté.
Recherchez @JoinTable dans le documentation hibernate pour des explications et des exemples.
Il est également plus simple d'utiliser @JoinTable
lorsqu'une entité peut être l'enfant dans plusieurs relations parent/enfant avec différents types de parents. Pour reprendre l'exemple de Behrang, imaginons qu'une tâche puisse être l'enfant du projet, de la personne, du département, de l'étude et du processus.
La table task
doit-elle comporter 5 nullable
zones de clé étrangère? Je crois que non...
Il vous permet de gérer plusieurs relations multiples. Exemple:
Table 1: post
post has following columns
____________________
| ID | DATE |
|_________|_________|
| | |
|_________|_________|
Table 2: user
user has the following columns:
____________________
| ID |NAME |
|_________|_________|
| | |
|_________|_________|
Join Table vous permet de créer un mappage en utilisant:
@JoinTable(
name="USER_POST",
joinColumns=@JoinColumn(name="USER_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="POST_ID", referencedColumnName="ID"))
va créer une table:
____________________
| USER_ID| POST_ID |
|_________|_________|
| | |
|_________|_________|