1. 序章

このクイックチュートリアルでは、@ManyToManyアノテーションを使用してHibernateでこのタイプの関係を指定する方法を簡単に説明します。

2. 典型的な例

簡単な実体関連図から始めましょう。これは、2つのエンティティ従業員プロジェクト間の多対多の関連付けを示しています:

このシナリオでは、任意の従業員を複数のプロジェクトに割り当てることができ、プロジェクトには複数の従業員が働いている可能性があり、2つの間に多対多の関連付けが発生します。

主キーとしてemployee_idを持つemployeeテーブルと、主キーとしてproject_idを持つprojectテーブルがあります。 ここでは、両側を接続するために結合テーブルemployee_projectが必要です。

3. データベースの設定

spring_hibernate_many_to_many。という名前のデータベースがすでに作成されていると仮定します。

また、employeeおよびprojectテーブルと、employee_idおよびproject_idを使用したemployee_project結合テーブルを作成する必要があります。外部キーとして:

CREATE TABLE `employee` (
  `employee_id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(50) DEFAULT NULL,
  `last_name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`employee_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

CREATE TABLE `project` (
  `project_id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`project_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;

CREATE TABLE `employee_project` (
  `employee_id` int(11) NOT NULL,
  `project_id` int(11) NOT NULL,
  PRIMARY KEY (`employee_id`,`project_id`),
  KEY `project_id` (`project_id`),
  CONSTRAINT `employee_project_ibfk_1` 
   FOREIGN KEY (`employee_id`) REFERENCES `employee` (`employee_id`),
  CONSTRAINT `employee_project_ibfk_2` 
   FOREIGN KEY (`project_id`) REFERENCES `project` (`project_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

データベースをセットアップしたら、次のステップはMavenの依存関係とHibernate構成の準備です。 詳細については、 Guide to Hibernate4 withSpringの記事を参照してください。

4. モデルクラス

モデルクラス従業員およびプロジェクトは、JPAアノテーションを使用して作成する必要があります。

@Entity
@Table(name = "Employee")
public class Employee { 
    // ...
 
    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
        name = "Employee_Project", 
        joinColumns = { @JoinColumn(name = "employee_id") }, 
        inverseJoinColumns = { @JoinColumn(name = "project_id") }
    )
    Set<Project> projects = new HashSet<>();
   
    // standard constructor/getters/setters
}
@Entity
@Table(name = "Project")
public class Project {    
    // ...  
 
    @ManyToMany(mappedBy = "projects")
    private Set<Employee> employees = new HashSet<>();
    
    // standard constructors/getters/setters   
}

ご覧のとおり、 EmployeeクラスとProjectクラスの両方が相互に参照しています。つまり、これらの間の関連付けは双方向です。

多対多の関連付けをマッピングするために、 @ManyToMany @JoinTable 、および@JoinColumnアノテーションを使用します。 それらを詳しく見てみましょう。

@ManyToMany アノテーションは、エンティティ間に多対多の関係を作成するために両方のクラスで使用されます。

この関連付けには2つの側面があります。 所有側と逆側。 この例では、所有側は従業員したがって、結合テーブルは、所有側でを使用して指定されます。 @JoinTable の注釈従業員クラス。 @JoinTable は、結合/リンクテーブルを定義するために使用されます。 この場合、 Employee_Project。

@JoinColumn アノテーションは、メインテーブルとの結合/リンク列を指定するために使用されます。 ここで、結合列は employee_id であり、 project_id は、 Project が関係の逆側にあるため、逆結合列です。

プロジェクトクラスでは、mappedBy属性が@ManyToManyアノテーションで使用され、従業員コレクションがコレクションによってマップされていることを示します。 X178X]プロジェクト所有者側のコレクション。

5. 実行

多対多のアノテーションの動作を確認するために、次のJUnitテストを作成できます。

public class HibernateManyToManyAnnotationMainIntegrationTest {
	private static SessionFactory sessionFactory;
	private Session session;

	//...

	@Test
        public void givenSession_whenRead_thenReturnsMtoMdata() {
	    prepareData();
       	    @SuppressWarnings("unchecked")
	    List<Employee> employeeList = session.createQuery("FROM Employee").list();
            @SuppressWarnings("unchecked")
	    List<Project> projectList = session.createQuery("FROM Project").list();
            assertNotNull(employeeList);
            assertNotNull(projectList);
            assertEquals(2, employeeList.size());
            assertEquals(2, projectList.size());
        
            for(Employee employee : employeeList) {
               assertNotNull(employee.getProjects());
               assertEquals(2, employee.getProjects().size());
            }
            for(Project project : projectList) {
               assertNotNull(project.getEmployees());
               assertEquals(2, project.getEmployees().size());
            }
        }

	private void prepareData() {
	    String[] employeeData = { "Peter Oven", "Allan Norman" };
	    String[] projectData = { "IT Project", "Networking Project" };
	    Set<Project> projects = new HashSet<Project>();

	    for (String proj : projectData) {
		projects.add(new Project(proj));
	    }

	    for (String emp : employeeData) {
		Employee employee = new Employee(emp.split(" ")[0], emp.split(" ")[1]);
		employee.setProjects(projects);
			
	        for (Project proj : projects) {
		    proj.getEmployees().add(employee);
		}
			
		session.persist(employee);
	    }
	}
	
	//...
}

データベースに作成された2つのエンティティ間の多対多の関係を確認できます。employee project 、および employee_project テーブルと、関係。

6. 結論

このチュートリアルでは、Hibernateの多対多の注釈を使用してマッピングを作成する方法を説明しました。これは、XMLマッピングファイルを作成するよりも便利です。

このチュートリアルのソースコードは、GitHubにあります。