68382


`@JoinColumn` と `mappedBy` の違いはなんですか？

[java - What's the difference between @JoinColumn and mappedBy when using a
JPA @OneToMany association - Stack
Overflow](https://stackoverflow.com/questions/11938253/whats-the-difference-
between-joincolumn-and-mappedby-when-using-a-jpa-onetoma)

ここに同じ質問がありますが、回答が乱立しており、要点がよくわかりませんでした。

よくわらないポイントとしては

`mappedBy` はこれひとつで双方向の設定ができるようだが、片方のオブジェクトに`mappedBy`を指定したにもかかわらず、反対側のオブジェクトにも
`@JoinColumn` をしている回答があることです。

なんだか回答に外部キーの話がでているようですが、この外部キーは文字通りDBのテーブル定義で外部キーを指定してることを指しているのか、ORマッパー的に外部キー的な動きをする意味合いで使っているのかニュアンスがいまいちつかめません。

（そもそも外部キーは置いておいて、`mappedBy`で双方向できるのであれば、`@JoinColumn`はいらないのではないかと思っていまいち頭に入ってきません）

外部キーは必ずしも指定しなくてもSQL的にはJoinできますが、JPAを使うのであれば必ずDB側で外部キーを指定しておかないといけないのでしょうか？


CC BY-SA 4.0
2020-07-07T04:16:40.370
68358
2021-01-06T23:33:12.903
2020-07-07T11:01:53.253
9008
9008
question
java jpa hibernate
@JoinColumn と mappedBy の違いはなんですか？


設定を省略した場合適切なデフォルト値が暗黙的に設定される、というのを念頭に置いておくと理解が進むかと思います。

デフォルト設定とは何か？というのはspec(やjavadoc)を見る必要があります。

  * [JSR 338: Java Persistence API, Version 2.2](https://github.com/javaee/jpa-spec/blob/master/jsr338-MR/JavaPersistence.pdf)

以下、カッコ内の数字列は上記specの参照節番号を表します。

* * *

リンク先の **`@OneToMany`に** `@JoinColumn` を付けた場合と `mappedBy` を付けた場合の違いは？の回答は、

  * `@JoinColumn` を付けることでデフォルトである join-table(2.9, 2.10.5) から join-column へマッピング戦略を変更する(11.1.40)。
  * `mappedBy` はinverse-side(FKを持っていない方のテーブルに対応するエンティ)から関連を辿る場合に付与する。つまり双方向関連にする(2.9, 2.10.2, 11.1.40)。  
なお`maapedBy`で指定したフィールドは `@ManyToOne` だが、 `@ManyToOne` はデフォルトで join-
column(2.10.3.2)なので結果としてjoin-columnマッピング戦略になる。

です。  
結果を比べると、 `@JoinColumn`は単方向、`mappedBy`は双方向のjoin-columnマッピング戦略の指定、ということになります。

* * *

> `mappedBy`
> はこれひとつで双方向の設定ができるようだが、片方のオブジェクトに`mappedBy`を指定したにもかかわらず、反対側のオブジェクトにも
> `@JoinColumn` をしている回答があることです。

[最もupvoteされている回答](https://stackoverflow.com/a/11938290/4506703)の

[code]

    @Entity
    public class Company {
        @OneToMany(fetch = FetchType.LAZY, mappedBy = "company")
        private List<Branch> branches;
    }
    
    @Entity
    public class Branch {
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "companyId")
        private Company company;
    }
    
[/code]

に登場する `@JoinColumn` は、 **`@ManyToOne`** に対する設定です。  
`@ManyToOne`は前述の通りデフォルトでjoin-
columnなので、マッピング戦略を変更する意図で`@JoinColumn`を付与しているわけではないです。  
`name`(カラム名)をデフォルト値である`company_id`(2.10.3.2,
11.1.25)から`companyId`へ変更するために付与しています。

> `mappedBy` で双方向できるのであれば、`@JoinColumn`はいらないのではないかと思っていまいち頭に入ってきません

(双方向かどうかとjoin-columnマッピング戦略を採るかどうかはそれぞれ独立した話ですが、)`@JoinColumn`が無くてもデフォルトでjoin-
columnマッピング戦略が採用されるので同じように動作する、という意味では不要だと言えます。

>
> なんだか回答に外部キーの話がでているようですが、この外部キーは文字通りDBのテーブル定義で外部キーを指定してることを指しているのか、ORマッパー的に外部キー的な動きをする意味合いで使っているのか

後者かと思います。join条件に使用するカラム(に対応するプロパティ)でしょう。

> 外部キーは必ずしも指定しなくてもSQL的にはJoinできますが、JPAを使うのであれば必ずDB側で外部キーを指定しておかないといけないのでしょうか？

FK制約が必須かどうか、ということであれば、必須ではないです。

* * *

余談ですが、回答者のうちの[Vlad
Mihalceaさん](https://stackoverflow.com/a/51055434/4506703)は、Hibernateコミュニティで
[色](https://github.com/hibernate/hibernate-orm/graphs/contributors)
[々](https://in.relation.to/vlad-mihalcea/index.html)
[と](https://vladmihalcea.com/books/)
お名前見かける方なんで、この方が回答していたらそれを信じれば良いのかな、というのが私の感覚としてはあります。  
(今回の回答は聞かれてないことまで答えてるので、少しずれてる感がしないでもないですが…)


CC BY-SA 4.0
2020-07-07T19:12:24.937
68382
2021-01-06T23:33:12.903
2021-01-06T23:33:12.903
2808
2808
68358
answer