1. ホーム
  2. java

[解決済み] JPAの@JoinTableアノテーションはどのような場合に使用するのですか?

2022-03-07 12:23:31

質問

どのような場合にJPA @JoinTable のアノテーションを使用してください。

解決方法は?

を編集 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 テーブルは、quot;Join Table"と呼ばれます。この2つ目のソリューションを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;

その結果、データベースはこうなっただろう。

最後に、多対多の関連付けのためのスキーマを作成したい場合、結合テーブルを使用することが唯一の解決策となります。