РЕДАКТИРОВАТЬ 2017-04-29 : Как указывалось некоторыми комментаторами, в примере JoinTable
не требуется атрибут аннотации mappedBy
. Фактически, последние версии Hibernate отказываются запускаться, печатая следующую ошибку:
org.hibernate.AnnotationException:
Associations marked as mappedBy must not define database mappings
like @JoinTable or @JoinColumn
Давайте представим, что у вас есть сущность с именем Project
и другая сущность с именем Task
, и у каждого проекта может быть много задач.
Вы можете спроектировать схему базы данных для этого сценария двумя способами.
Первое решение - создать таблицу с именем Project
и другую таблицу с именем Task
и добавить столбец внешнего ключа в таблицу задач с именем project_id
:
Project Task
------- ----
id id
name name
project_id
Таким образом, будет возможно определить проект для каждой строки в таблице задач. Если вы используете этот подход, в ваших классах сущностей вам не понадобится таблица соединений:
@Entity
public class Project {
@OneToMany(mappedBy = "project")
private Collection<Task> tasks;
}
@Entity
public class Task {
@ManyToOne
private Project project;
}
Другое решение - использовать третью таблицу, например, Project_Tasks
и сохранить отношения между проектами и задачами в этой таблице:
Project Task Project_Tasks
------- ---- -------------
id id project_id
name name task_id
Таблица Project_Tasks
называется «Соединительной таблицей». Для реализации этого второго решения в JPA вам необходимо использовать аннотацию @JoinTable
. Например, чтобы реализовать однонаправленную связь «один ко многим», мы можем определить наши сущности так:
Project
сущность:
@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
лицо:
@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;
}
}
Это создаст следующую структуру базы данных:
Аннотация @JoinTable
также позволяет настраивать различные аспекты таблицы соединений. Например, если бы мы аннотировали свойство tasks
следующим образом:
@JoinTable(
name = "MY_JT",
joinColumns = @JoinColumn(
name = "PROJ_ID",
referencedColumnName = "PID"
),
inverseJoinColumns = @JoinColumn(
name = "TASK_ID",
referencedColumnName = "TID"
)
)
@OneToMany
private List<Task> tasks;
Результирующая база данных стала бы:
Наконец, если вы хотите создать схему для связи «многие ко многим», единственным доступным решением будет использование таблицы соединений.