サーチ…


前書き

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})を記述する必要があります。そうしないと、子が削除されると親データが削除されます。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow