どの場合、JPA @JoinTable
アノテーションを使用しますか?
EDIT 2017-04-29:一部のコメンターが指摘したように、JoinTable
の例にはmappedBy
アノテーション属性は必要ありません。実際、Hibernateの最近のバージョンは、次のエラーを出力して起動を拒否します。
org.hibernate.AnnotationException:
Associations marked as mappedBy must not define database mappings
like @JoinTable or @JoinColumn
Project
という名前のエンティティとTask
という名前の別のエンティティがあり、各プロジェクトに多くのタスクがある可能性があるとします。
このシナリオのデータベーススキーマは、2つの方法で設計できます。
最初の解決策は、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;
}
他の解決策は、3番目のテーブルを使用することです。 Project_Tasks
、およびプロジェクトとタスク間の関係をそのテーブルに保存します。
Project Task Project_Tasks
------- ---- -------------
id id project_id
name name task_id
Project_Tasks
テーブルは「Join Table」と呼ばれます。この2番目のソリューションをJPAに実装するには、@JoinTable
アノテーションを使用する必要があります。たとえば、単方向の1対多の関連付けを実装するために、エンティティを次のように定義できます。
Project
entity:
@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:
@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;
結果のデータベースは次のようになります。
最後に、多対多の関連付けのスキーマを作成する場合は、結合テーブルを使用することが唯一の解決策です。
ManyToMany関連付けをマップする唯一のソリューションです。関連付けをマップするには、エンティティテーブルとテーブルの間に結合テーブルが必要です。
また、多くのサイドのテーブルに外部キーを追加したくないため、OneToMany(通常は単方向)アソシエーションにも使用されます。
説明と例については、 hibernate documentation で@JoinTableを検索してください。
また、エンティティが異なるタイプの親との複数の親/子関係の子になる可能性がある場合は、@JoinTable
を使用する方がクリーンです。 Behrangの例をフォローアップするために、タスクがProject、Person、Department、Study、およびProcessの子になることができると想像してください。
task
テーブルには、5つのnullable
外部キーフィールドが必要ですか?私はそうは思いません...
多対多の関係を処理できます。例:
Table 1: post
post has following columns
____________________
| ID | DATE |
|_________|_________|
| | |
|_________|_________|
Table 2: user
user has the following columns:
____________________
| ID |NAME |
|_________|_________|
| | |
|_________|_________|
結合テーブルでは、次を使用してマッピングを作成できます。
@JoinTable(
name="USER_POST",
joinColumns=@JoinColumn(name="USER_ID", referencedColumnName="ID"),
inverseJoinColumns=@JoinColumn(name="POST_ID", referencedColumnName="ID"))
テーブルを作成します:
____________________
| USER_ID| POST_ID |
|_________|_________|
| | |
|_________|_________|