🍈
JPAの@OneToManyとは
@OneToMany(一対多)片方向
属性 | 説明 | ディフォルト値 |
---|---|---|
mappedBy | 連関関係のオーナーを選択する | |
fetch | fetch戦略を決める | FetchType.LAZY |
cascade | persistenceの遷移機能 | |
targetEntity | type情報を設定する、ほとんど使わない |
- 一対多片方向は一(1)が関係マッピングのオーナーになること。
- つまり一(1)のオブジェクトからFKを管理すること。
- 反面テーブルの一対多の関係は常に多の方にFKがある。
- オブジェクトとテーブルの違いにより反対側のテーブルのFKを管理する特殊な構造
- この一対多片方向を使うときは必ず
@JoinColumn(name="FK")
を使用しなければ成らない。そうでないと@JoinTable
戦略が基本戦略として使用され中間テーブルを作ってしまう。
Member.java
@Entity // JPAが管理するオブジェクト
@Table(name = "member")
@Getter @Setter
public class Member {
@Id
private Long id;
private String name;
//片方向関係なのでMemberには何もない
}
Team.java
@Entity
@Setter @Getter
public class Team {
@Id
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "team_id") // 1の方でFKを管理する
private List<Member> members = new ArrayList<>();
}
- 上の二つのEntityに値を入れてみると
JpaMain.java
Member member = new Member();
member.setId(1L);
member.setName("basic");
Team team = new Team();
team.setId(1L);
team.setName("TeamA");
// ??
team.getMembers().add(member);
manager.persist(member);
manager.persist(team);
- 上のコードを実行したときのsql
Hibernate:
/* insert jpabasic.Member
*/ insert
into
member
(name, id)
values
(?, ?)
Hibernate:
/* insert jpabasic.Team
*/ insert
into
Team
(name, id)
values
(?, ?)
Hibernate:
/* create one-to-many row jpabasic.Team.members */
update
member
set
team_id=?
where
id=?
- 何とupdate文が出てる。
- Entity(
Team
)が管理するFKが他のテーブル(Member
)にあるため - 関係マッピングの管理のためUPDATE文が追加で実行される
- この関係は性能上問題が多い、
- 1にFKがある事だけでもデメリットになる
- 使わないほうがいい
- この関係より多対一双方向を使えばいい
一対多(@OneToMany)双方向
- 一対多双方向は公式的に存在しないが
@JoinColumn(name="FK", insertable=false, updatable=false)
- を利用して読み取り専用フィールドを作り双方向みたいに使う方法
- 公式に存在もしない方法だし使わないほうがいい
- 多対一双方向を使えばいい
Team.java
@Entity
@Setter @Getter
public class Team {
@Id
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "team_id") // 1の方でFKを管理する
private List<Member> members = new ArrayList<>();
}
Member.java
@Entity // JPAが管理するオブジェクト
@Table(name = "member")
@Getter @Setter
public class Member {
@Id
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "team_id", insertable=false, updatable=false)
private Team team; // 読み取り専用にする
}
次(@OneToOne)
Discussion