サーチ…
前書き
ManyToMany
マッピングは、エンティティ間の関係を記述します。エンティティ間の関係は、相互に複数のインスタンスに関連付けることができ、 @ManyToMany
アノテーションで定義されます。
エンティティのテーブル内の外部キー列が使用できる@OneToMany
とは異なり、 ManyToMany
はエンティティを相互にマップする結合テーブルが必要です。
パラメーター
注釈 | 目的 |
---|---|
@TableGenerator | GeneratedValue アノテーションにジェネレータ要素が指定されたときに、名前で参照される主キージェネレータを定義します |
@GeneratedValue | 主キーの値の生成戦略の指定を提供します。 Idアノテーションと共に、エンティティまたはマップされたスーパークラスのプライマリキーのプロパティまたはフィールドに適用できます。 |
@ManyToMany | 多くの従業員が複数のプロジェクトで作業できるように、従業員とプロジェクトのエンティティ間の関係を指定します。 |
mappedBy="projects" | 従業員とプロジェクトの間の双方向の関係を定義する |
@JoinColumn | 関連の所有者とみなされるエンティティを参照する列の名前を指定します。 |
@JoinTable | 外部キーを使用して従業員とプロジェクトの関係を保持するデータベース内のテーブルを指定します。 |
備考
- @TableGeneratorと@GeneratedValueは、jpaテーブルジェネレータを使用した自動ID作成に使用されます。
- @ManyToManyアノテーションは、従業員とプロジェクトエンティティの関係を指定します。
- @JoinTableは、joinテーブルjpaとして使用するテーブルの名前を指定します.name = "employee_project"を使用してEmployeeとProjectの間の多対多のマッピング。これは、データベーステーブルに他のテーブルを参照するための外部キーが含まれていないため、jpa多対多マッピングの所有権を判断する方法がないために行われます。
- @JoinColumnは、関連の所有者とみなされるエンティティを参照する列の名前を指定し、@inverseJoinColumnは関係の逆側の名前を指定します。 (あなたは所有者とみなされるように任意の面を選ぶことができます。ここではEmployeeをオーナーとして選択していますので、@JoinColumnはemployee_projectというジョインテーブルのidemployeeカラムを参照し、@InverseJoinColumnはjpaの逆側のidprojectを参照します。
- Projectエンティティの@ManyToManyアノテーションは逆の関係を示しますので、mappedBy = projectsを使用してEmployeeエンティティのフィールドを参照します。
従業員からプロジェクトへの多対多マッピング
従業員エンティティ。
package com.thejavageek.jpa.entities;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.TableGenerator;
@Entity
public class Employee {
@TableGenerator(name = "employee_gen", table = "id_gen", pkColumnName = "gen_name", valueColumnName = "gen_val", allocationSize = 100)
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "employee_gen")
private int idemployee;
private String name;
@ManyToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "employee_project", joinColumns = @JoinColumn(name = "idemployee"), inverseJoinColumns = @JoinColumn(name = "idproject"))
private List<Project> projects;
public int getIdemployee() {
return idemployee;
}
public void setIdemployee(int idemployee) {
this.idemployee = idemployee;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Project> getProjects() {
return projects;
}
public void setProjects(List<Project> projects) {
this.projects = projects;
}
}
プロジェクトエンティティ:
package com.thejavageek.jpa.entities;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.TableGenerator;
@Entity
public class Project {
@TableGenerator(name = "project_gen", allocationSize = 1, pkColumnName = "gen_name", valueColumnName = "gen_val", table = "id_gen")
@Id
@GeneratedValue(generator = "project_gen", strategy = GenerationType.TABLE)
private int idproject;
private String name;
@ManyToMany(mappedBy = "projects", cascade = CascadeType.PERSIST)
private List<Employee> employees;
public int getIdproject() {
return idproject;
}
public void setIdproject(int idproject) {
this.idproject = idproject;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
テストコード
/ * EntityManagerFactoryを作成する* / EntityManagerFactory emf =永続性.createEntityManagerFactory( "JPAExamples");
/* Create EntityManager */
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Employee prasad = new Employee();
prasad.setName("prasad kharkar");
Employee harish = new Employee();
harish.setName("Harish taware");
Project ceg = new Project();
ceg.setName("CEG");
Project gtt = new Project();
gtt.setName("GTT");
List<Project> projects = new ArrayList<Project>();
projects.add(ceg);
projects.add(gtt);
List<Employee> employees = new ArrayList<Employee>();
employees.add(prasad);
employees.add(harish);
ceg.setEmployees(employees);
gtt.setEmployees(employees);
prasad.setProjects(projects);
harish.setProjects(projects);
em.persist(prasad);
transaction.commit();
埋め込み可能なアノテーションなしで複合キーを処理する方法
あなたが持っている場合
Role:
+-----------------------------+
| roleId | name | discription |
+-----------------------------+
Rights:
+-----------------------------+
| rightId | name | discription|
+-----------------------------+
rightrole
+------------------+
| roleId | rightId |
+------------------+
上記のシナリオでは、 rightrole
テーブルに複合キーがあり、JPAユーザーにアクセスするにはEmbeddable
アノテーションを使用してエンティティを作成する必要があります。
このような:
右ロールテーブルのエンティティは次のとおりです。
@Entity
@Table(name = "rightrole")
public class RightRole extends BaseEntity<RightRolePK> {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected RightRolePK rightRolePK;
@JoinColumn(name = "roleID", referencedColumnName = "roleID", insertable = false, updatable = false)
@ManyToOne(fetch = FetchType.LAZY)
private Role role;
@JoinColumn(name = "rightID", referencedColumnName = "rightID", insertable = false, updatable = false)
@ManyToOne(fetch = FetchType.LAZY)
private Right right;
......
}
@Embeddable
public class RightRolePK implements Serializable {
private static final long serialVersionUID = 1L;
@Basic(optional = false)
@NotNull
@Column(nullable = false)
private long roleID;
@Basic(optional = false)
@NotNull
@Column(nullable = false)
private long rightID;
.....
}
埋め込み可能な注釈は単一オブジェクトの場合は問題ありませんが、一括レコードを挿入する際に問題が発生します。
問題は、ユーザーがrights
role
持つ新しいrole
を作成し、最初のユーザーがrole
オブジェクトをstore(persist)
必要があり、その後、ユーザーがflush
を実行して、新しく生成されたid
をロールとして取得する必要があるときです。ユーザーはそれをrightrole
エンティティのオブジェクトに入れることができます。
このユーザーを解決するには、エンティティをわずかに異なる方法で書き込むことができます。
ロールテーブルのエンティティは次のとおりです。
@Entity
@Table(name = "role")
public class Role {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@NotNull
@Column(nullable = false)
private Long roleID;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "role", fetch = FetchType.LAZY)
private List<RightRole> rightRoleList;
@ManyToMany(cascade = {CascadeType.PERSIST})
@JoinTable(name = "rightrole",
joinColumns = {
@JoinColumn(name = "roleID", referencedColumnName = "ROLE_ID")},
inverseJoinColumns = {
@JoinColumn(name = "rightID", referencedColumnName = "RIGHT_ID")})
private List<Right> rightList;
.......
}
@JoinTable注釈は、エンティティがなくてもrightrole
テーブルに挿入されます(そのテーブルのroleとrightのidカラムのみがある限り)。
ユーザーは簡単に次のことができます。
Role role = new Role();
List<Right> rightList = new ArrayList<>();
Right right1 = new Right();
Right right2 = new Right();
rightList.add(right1);
rightList.add(right2);
role.setRightList(rightList);
inverseJoinColumnsに@ManyToMany(cascade = {CascadeType.PERSIST})を記述する必要があります。そうしないと、子が削除されると親データが削除されます。