수색…


소개

ManyToMany 매핑은 둘 다 서로의 인스턴스에 관련 될 수 있고 @ManyToMany 주석으로 정의되는 엔티티 간의 관계를 설명합니다.

엔티티 테이블의 외래 키 열을 사용할 수있는 @OneToMany 와 달리 ManyToMany 는 엔티티를 서로 매핑하는 조인 테이블을 필요로합니다.

매개 변수

주석 목적
@TableGenerator GeneratedValue 주석에 Generator 요소가 지정 될 때 이름으로 참조 될 수있는 기본 키 생성기를 정의합니다.
@GeneratedValue 기본 키 값에 대한 생성 전략 지정을 제공합니다. Id 주석과 함께 엔티티 나 매핑 된 수퍼 클래스의 기본 키 속성이나 필드에 적용될 수 있습니다.
@ManyToMany 많은 직원이 여러 프로젝트에서 작업 할 수 있도록 직원과 프로젝트 엔티티 간의 관계를 지정합니다.
mappedBy="projects" 직원과 프로젝트 간의 양방향 관계를 정의합니다.
@JoinColumn 연결의 소유자로 간주 될 엔터티를 참조하는 열의 이름을 지정합니다.
@JoinTable 외래 키를 사용하여 직원 대 프로젝트 관계를 유지할 데이터베이스의 테이블을 지정합니다.

비고

  • @TableGenerator 및 @GeneratedValue는 jpa 테이블 생성기를 사용하여 자동 ID 생성에 사용됩니다.
  • @ManyToMany 주석은 직원과 프로젝트 엔티티 간의 관계를 지정합니다.
  • @JoinTable은 조인 테이블로 사용할 테이블의 이름을 지정합니다. jpa name = "employee_project"를 사용하여 Employee와 Project간에 많은 매핑을합니다. 이것은 데이터베이스 테이블이 다른 테이블을 참조하는 외래 키를 포함하지 않기 때문에 jpa many to many 매핑의 소유권을 결정할 방법이 없기 때문에 수행됩니다.
  • @JoinColumn은 연관의 소유자로 간주 될 엔티티를 참조하는 열의 이름을 지정하고 @inverseJoinColumn은 관계의 반대면의 이름을 지정합니다. (당신은 주인으로 여겨지는 어느 쪽이라도 선택할 수 있습니다. 우리의 경우 Employee를 소유자로 선택했기 때문에 @JoinColumn은 employee_project 조인 테이블에서 idemployee 열을 참조하고 @InverseJoinColumn은 jpa many to many 매핑의 역변환 인 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();

Embeddable 어노테이션없이 복합 키를 처리하는 방법

당신이 가지고 있다면

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


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

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

위의 시나리오에서 rightrole 테이블은 복합 키를 가지고 있으며 JPA 사용자에게 액세스하려면 Embeddable 어노테이션으로 엔티티를 생성해야합니다.

이렇게 :

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;

   .....

}

삽입 가능한 주석은 단일 객체에 적합하지만 대량 레코드를 삽입하는 동안 문제가 발생합니다.

문제는 사용자가 rightsrole 을 만들려고 할 때마다 첫 번째 사용자가 role 객체를 store(persist) 하고 사용자가 새로 생성 된 id 하여 역할을 새로 flush 할 때입니다. 다음 사용자가 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 테이블에 삽입되도록 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