Ricerca…


introduzione

Una mappatura ManyToMany descrive una relazione tra entità in cui entrambe possono essere correlate a più istanze l'una dell'altra ed è definita @ManyToMany .

A differenza di @OneToMany cui è possibile utilizzare una colonna di chiave esterna nella tabella dell'entità, ManyToMany richiede una tabella di join, che associa le entità l'una all'altra.

Parametri

Annotazione Scopo
@TableGenerator Definisce un generatore di chiavi primarie a cui è possibile fare riferimento per nome quando viene specificato un elemento generatore per l'annotazione GeneratedValue
@GeneratedValue Fornisce la specifica delle strategie di generazione per i valori delle chiavi primarie. Può essere applicato a una proprietà o campo chiave primaria di un'entità o superclasse mappata insieme all'annotazione Id.
@ManyToMany Specifica la relazione tra Employee e entità del progetto in modo tale che molti dipendenti possano lavorare su più progetti.
mappedBy="projects" Definisce una relazione bidirezionale tra Impiegato e Progetto
@JoinColumn Specifica il nome della colonna che farà riferimento all'entità da considerare come proprietario dell'associazione
@JoinTable Specifica la tabella nel database che manterrà dipendente per proiettare le relazioni utilizzando chiavi esterne

Osservazioni

  • @TableGenerator e @GeneratedValue vengono utilizzati per la creazione automatica dell'ID utilizzando il generatore di tabelle jpa.
  • @ManyToMany annotation specifica la relazione tra Employee e Project entities.
  • @JoinTable specifica il nome della tabella da utilizzare come tabella di join jpa da molti a molti tra Employee e Project usando name = "employee_project". Ciò avviene perché non è possibile determinare la proprietà di un mapping jpa molti a molti poiché le tabelle del database non contengono chiavi esterne per fare riferimento ad altre tabelle.
  • @JoinColumn specifica il nome della colonna che farà riferimento all'entità da considerare come proprietario dell'associazione mentre @inverseJoinColumn specifica il nome del lato inverso della relazione. (Puoi scegliere qualsiasi lato per essere considerato come proprietario. Assicurati solo che quei lati siano in relazione). Nel nostro caso abbiamo scelto Employee come proprietario in modo che @JoinColumn faccia riferimento alla colonna idemployee nella tabella join employee_project e @InverseJoinColumn fa riferimento a idproject che è il lato inverso di jpa molti a molti mapping.
  • @ManyToMany annotation nell'entità Project mostra una relazione inversa, quindi utilizza mappedBy = projects per fare riferimento al campo nell'entità Employee.

L'esempio completo può essere riferito qui

Dipendente per la mappatura da molti a molti

Entità dipendente.

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

}

Entità del progetto:

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

}

Codice di prova

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

Come gestire la chiave composta senza annotazione incorporabile

Se hai

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


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

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

Nella tabella rightrole sopra lo scenario è presente una chiave composta e per accedervi nell'utente JPA è necessario creare un'entità con annotazione Embeddable .

Come questo:

L'entità per la tabella del rightrole è:

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

   .....

}

L'annotazione incorporabile va bene per un singolo oggetto ma causerà un problema durante l'inserimento di record di massa.

Il problema è che ogni volta che l'utente vuole creare un nuovo role con rights primo utente deve store(persist) oggetto role e quindi l'utente deve eseguire lo flush per ottenere l' id appena generato per il ruolo. allora e poi l'utente può inserirlo rightrole dell'entità rightrole .

Per risolvere questo utente si può scrivere un'entità leggermente diversa.

L'entità per la tabella dei ruoli è:

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

L'annotazione @JoinTable si prenderà cura dell'inserimento nella tabella rightrole anche senza un'entità (purché tale tabella abbia solo le colonne id del ruolo e destra).

L'utente può quindi semplicemente:

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

Devi scrivere @ManyToMany (cascade = {CascadeType.PERSIST}) in inverseJoinColumns altrimenti i tuoi dati parent verranno cancellati se il figlio viene cancellato.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow