Suche…


Einführung

Ein ManyToMany Mapping beschreibt eine Beziehung zwischen Entitäten, bei denen beide mehr als eine Instanz voneinander betreffen können, und wird durch die Annotation @ManyToMany definiert.

Im Gegensatz zu @OneToMany wo eine Fremdschlüsselspalte in der Entitätstabelle verwendet werden kann, benötigt ManyToMany eine Join-Tabelle, die die Entitäten einander zuordnet.

Parameter

Anmerkung Zweck
@TableGenerator Definiert einen Primärschlüsselgenerator, auf den anhand des Namens verwiesen werden kann, wenn ein Generatorelement für die GeneratedValue Annotation angegeben wird
@GeneratedValue Ermöglicht die Angabe von Generierungsstrategien für die Werte von Primärschlüsseln. Sie kann in Verbindung mit der Id-Annotation auf eine Primärschlüsseleigenschaft oder ein Feld einer Entität oder einer zugeordneten Superklasse angewendet werden.
@ManyToMany Gibt die Beziehung zwischen Employee- und Project-Entitäten an, sodass viele Mitarbeiter an mehreren Projekten arbeiten können.
mappedBy="projects" Definiert eine bidirektionale Beziehung zwischen Mitarbeiter und Projekt
@JoinColumn Gibt den Namen der Spalte an, die sich auf die Entität bezieht, die als Eigentümer der Zuordnung betrachtet wird
@JoinTable Gibt die Tabelle in der Datenbank an, in der Mitarbeiter mithilfe von Fremdschlüsseln projektiert werden

Bemerkungen

  • @TableGenerator und @GeneratedValue werden für die automatische ID-Erstellung mit dem jpa-Tabellengenerator verwendet.
  • Die Annotation @ManyToMany gibt die Beziehung zwischen Entitäten Employee und Project an.
  • @JoinTable gibt den Namen der Tabelle an, die als Join-Tabelle verwendet werden soll. Viele Zuordnungen zwischen Employee und Project mit name = "employee_project". Dies geschieht, da es keine Möglichkeit gibt, den Besitz einer Jpa-Many-To-Mapping-Zuordnung zu bestimmen, da die Datenbanktabellen keine Fremdschlüssel enthalten, die auf andere Tabellen verweisen.
  • @JoinColumn gibt den Namen der Spalte an, die sich auf die Entität bezieht, die als Eigentümer der Zuordnung betrachtet wird, während @inverseJoinColumn den Namen der inversen Seite der Beziehung angibt. (Sie können eine beliebige Seite als Eigentümer auswählen. Stellen Sie nur sicher, dass diese Seiten in Beziehung stehen). In unserem Fall haben wir Employee als Eigentümer ausgewählt, sodass @JoinColumn auf die idemployee-Spalte in der join-Tabelle employee_project und @InverseJoinColumn auf idproject verweist, das eine inverse Seite von jpa viele in viele darstellt.
  • Die @ManyToMany-Annotation in der Projektentität zeigt eine umgekehrte Beziehung. Daher verwendet sie mappedBy = -Projekte, um auf das Feld in der Mitarbeiterentität zu verweisen.

Ein vollständiges Beispiel kann hier herangezogen werden

Mitarbeiter projizieren viele zu viele Mapping

Mitarbeiter-Entität

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;
    }

}

Projekteinheit:

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;
    }

}

Testcode

/ * EntityManagerFactory erstellen * / EntityManagerFactory emf = Persistenz .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();

Umgang mit zusammengesetztem Schlüssel ohne eingebettete Annotation

Wenn Sie haben

Role:
+-----------------------------+
| roleId | name | discription |
+-----------------------------+


Rights:
+-----------------------------+
| rightId | name | discription|
+-----------------------------+

rightrole
+------------------+
| roleId | rightId | 
+------------------+

In obigem Szenario hat die rightrole Tabelle einen zusammengesetzten Schlüssel und für den Zugriff auf JPA muss der Benutzer eine Entität mit Embeddable Annotation erstellen.

So was:

Entität für Rightrole-Tabelle ist:

    @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;

   .....

}

Die eingebettete Annotation ist für einzelne Objekte geeignet, führt jedoch beim Einfügen von Massendatensätzen zu einem Problem.

Das Problem ist , wenn Benutzer neue erstellen möchten role mit rights dann erste Nutzer müssen store(persist) role Objekt und dann Benutzer zu tun haben , flush neu erzeugten zu bekommen id für Rolle. dann kann der Benutzer es in das Objekt der rightrole Instanz rightrole .

Um dieses Problem zu lösen, kann der Benutzer etwas anders schreiben.

Entität für Rollentabelle ist:

@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;
.......
}

Die Annotation @JoinTable sorgt für das Einfügen in die rightrole Tabelle auch ohne Entität (sofern diese Tabelle nur die id-Spalten der Rolle und des Rechtes hat).

Der Benutzer kann dann einfach:

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);

Sie müssen @ManyToMany (cascade = {CascadeType.PERSIST}) in inverseJoinColumns schreiben. Andernfalls werden Ihre übergeordneten Daten gelöscht, wenn das untergeordnete Element gelöscht wird.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow