EclipseLink – 11 – Relationship – 05 – Many To Many

Merhaba Arkadaslar
Bu bolumde ManyToMany iliskisini inceleyecegiz. ManyToMany de Collection-Valued ozellige sahiptir.

Many To Many Mapping

ManyToMany iliskide karsilikli olarak cardinality(nicelik) many ozelligi gosterir. Ornegin calisan(Employee) ve proje(Project) kavramlarini dusundugumuzde bir calisan birden fazla projede yer alabilir , benzer sekilde bir projede birden fazla calisan gorev alabilir. Ya da bir baska ornek olarak bir ogrenci birden fazla ders secebilir , ayni dersi birden fazla ogrenci alabilir. Kisacasi gercek hayattan ornekleri cogaltmak mumkun.

Unidirectional ManyToMany Relationship
Bu durumda sadece bir Entity’de @ManyToMany annotation tanimli olacak. Hedef nicelik (target cardinality) Many oldugu icin java.util.Collection kullanmamiz gereklidir. Bu Collection’in elemanlari target/hedef Entity tipinde olmalidir.

unidirectional manytomany relationship

Project.java

package _19.manyToMany.uni.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Project {

	@Id
	@GeneratedValue(strategy = GenerationType.TABLE)
	private int id;
	private String name;
	
	//constructors
	//getters and setters
	//toString
	
}

Employee19.java

package _19.manyToMany.uni.model;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

@Entity
public class Employee19 {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private int id;
    private String name;
    private String surname;
    private int salary;

    @ManyToMany
    private List<Project> projects;

    //constructors
    //getters and setters
    //toString

}

Employee19 sinifimizda @ManyToMany annotation’i List<Project> ile birlikte kullaniyoruz. Project sinifimizda List<Employee19> tipinde bir degisken bulunmuyor. Dolayisiyla burada unidirectional ManyToMany iliski soz konusudur.

EmployeeTest.java

package _19.manyToMany.uni.test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import _19.manyToMany.uni.model.Employee19;
import _19.manyToMany.uni.model.Project;
import _19.manyToMany.uni.service.EmployeeService;
import _19.manyToMany.uni.service.EmployeeServiceImpl;
import _19.manyToMany.uni.service.ProjectService;
import _19.manyToMany.uni.service.ProjectServiceImpl;

public class EmployeeTest {

	public static void main(String[] args) {
		EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("EmployeePersistenceUnit");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		EntityTransaction entityTransaction = entityManager.getTransaction();

		EmployeeService employeeService = new EmployeeServiceImpl(entityManager);

		entityTransaction.begin();
		Employee19 employee = employeeService.createEmployee("Levent", "Erguder", 1000);
		Employee19 employee2 = employeeService.createEmployee("James", "Gosling", 10000);
		Employee19 employee3 = employeeService.createEmployee("Joshua", "Bloch", 10000);
		entityTransaction.commit();

		System.out.println("Persisted :" + employee);
		System.out.println("Persisted :" + employee);
		System.out.println("Persisted :" + employee);

		ProjectService phoneService = new ProjectServiceImpl(entityManager);

		entityTransaction.begin();
		Project project = phoneService.createProject("Project1");
		Project project2 = phoneService.createProject("Project2");
		Project project3 = phoneService.createProject("Project3");
		entityTransaction.commit();

		System.out.println("Persisted :" + project);
		System.out.println("Persisted :" + project2);
		System.out.println("Persisted :" + project3);

		entityTransaction.begin();
		employee.getProjects().add(project);
		employee.getProjects().add(project2);

		employee2.getProjects().add(project2);
		employee2.getProjects().add(project3);

		employee3.getProjects().add(project);
		employee3.getProjects().add(project2);
		employee3.getProjects().add(project3);
		entityTransaction.commit();

		entityManager.close();
		entityManagerFactory.close();

	}
}

Ornegimizi inceleyecek olursak 3 tane Employee19 objesi ve 3 tane Project objesi olusturuyoruz. 3 Project objesini List<Project> projects listesine ekliyoruz.

Ornegimizi calistirdigimizda 3 tane tablo olusacaktir ;

manytomany employee department

  • Employee19
  • Project
  • Employee19_Project

Employee19_Project tablosundaki kolonlar ise

  • Employee19_Id ( Owning side table name_primarykey)
  • Projects_Id (projects tablo isminden gelmiyor ! Employee19 sinifimizdaki List<Project> projects isminden gelmektedir. “id” degeri ise Project tablosunun primary key degeridir.)
  • Benzer durumu bir onceki bolumde de belirtmistim.

@JoinTable annotation’da name parametresi ile tablomuzun varsayilan ismini degistiririz. joinColumns ve inverseJoinColumns parametresi ve @JoinColumn annotation ile tablomuzdaki varsayilan kolon isimlerini degistiriyoruz.

	@ManyToMany
        @JoinTable(name="EMP_PRJ",
    	    joinColumns=@JoinColumn(name="EMP_ID"),
    	    inverseJoinColumns=@JoinColumn(name="PRJ_ID") )  	
	private List<Project> projects;

manytomany jointable

@JoinTable annotation da belirtigimiz EMP_PRJ tablomuz olustu. Kolon isimlerimiz de varsayilan isimler yerine joinColumns ve inverseJoinColumns parametresiyle belirttigimiz EMP_ID ve PRJ_ID olacaktir.

Bidirectional ManyToMany Relationship
Bu durumda 2 Entity karsilikli olarak bir Collection’a sahip olacaklar. ManyToMany iliskide owning side tercihe baglidir. mappedBy parametresi inverse side belirtir. Eger mappedBy parametresi kullanilmazsa bu durumda 2 tane Unidirectional ManyToMany iliski soz konusu olacaktir.

bidirectional manytomany relationship

Employee20.java

package _20.manyToMany.bi.model;

import java.util.ArrayList;
import java.util.List;

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;

@Entity
public class Employee20 {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private int id;
    private String name;
    private String surname;
    private int salary;

    @ManyToMany
    @JoinTable(name="EMP_PRJ_BI",
        joinColumns=@JoinColumn(name="EMP_ID"),
        inverseJoinColumns=@JoinColumn(name="PRJ_ID") )     
    private List<Project2> project;

    //constructors
    //getters and setter
    //toString
}

Project2.java

package _20.manyToMany.bi.model;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

@Entity
public class Project2 {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private int id;
    private String name;

    @ManyToMany(mappedBy = "projects")
    private List<Employee20> employees;

    //constructors
    //getters and setter
    //toString

}

Project2 sinifi elemanlari Employee20 olan bir List instance variable/field e sahip ve @ManyToMany annotation ekliyoruz. Inverse side olarak Project2 tarafini belirledigimiz icin mappedBy annotation burada yer alacaktir. Bu durum tamamen secimliktir dilersek Employee20 tarafi inverse side olabilirdi.

Daha onceki orneklerde belirttigim gibi bidirectional da olsa otomatik olarak karsilikli setter islemleri yapilmaz. Benzer sekilde burada da karsilikli olarak List’lere elemanlari eklememiz gereklidir. Bunun icin Employee20 sinifimiza ufak bir metot yazabiliriz ya da test metodunda da karsilikli olarak ekleyebiliriz.

	public void addLists(Project2 project) {
		// bidirectional bir iliskide karsilikli olarak elemanlari List'lere
		// eklememiz gereklidir.
		if (!getProjects().contains(project)) {
			getProjects().add(project);
		}
		if (!project.getEmployees().contains(this)) {
			project.getEmployees().add(this);
		}
	}

addLists metotu yerine EmployeeTest metodunda  su sekilde de yapabiliriz.

		//employee.getProjects().add(project);
		//project.getEmployees().add(employee);

EmployeeTest.java

package _20.manyToMany.bi.test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import _20.manyToMany.bi.model.Employee20;
import _20.manyToMany.bi.model.Project2;
import _20.manyToMany.bi.service.EmployeeService;
import _20.manyToMany.bi.service.EmployeeServiceImpl;
import _20.manyToMany.bi.service.ProjectService;
import _20.manyToMany.bi.service.ProjectServiceImpl;

public class EmployeeTest {

	public static void main(String[] args) {
		EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("EmployeePersistenceUnit");
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		EntityTransaction entityTransaction = entityManager.getTransaction();

		EmployeeService employeeService = new EmployeeServiceImpl(entityManager);

		entityTransaction.begin();
		Employee20 employee = employeeService.createEmployee("Levent", "Erguder", 1000);
		Employee20 employee2 = employeeService.createEmployee("James", "Gosling", 10000);
		Employee20 employee3 = employeeService.createEmployee("Joshua", "Bloch", 10000);
		entityTransaction.commit();

		System.out.println("Persisted :" + employee);
		System.out.println("Persisted :" + employee);
		System.out.println("Persisted :" + employee);

		ProjectService phoneService = new ProjectServiceImpl(entityManager);

		entityTransaction.begin();
		Project2 project = phoneService.createProject("Project1");
		Project2 project2 = phoneService.createProject("Project2");
		Project2 project3 = phoneService.createProject("Project3");
		entityTransaction.commit();

		System.out.println("Persisted :" + project);
		System.out.println("Persisted :" + project2);
		System.out.println("Persisted :" + project3);

		entityTransaction.begin();
		// bidirectional bir iliskide karsilikli olarak elemanlari List'lere
		// eklememiz gereklidir.
		//addLists metodunda
		// List project2;
		// List employees;
		// listelerine elemanlar eklenmektedir.
		
		employee.addLists(project);
		
		//addLists metotu yerine su sekilde de yapabiliriz. 
		//employee.getProjects().add(project);
		//project.getEmployees().add(employee);
		
		employee.addLists(project2);

		employee2.addLists(project2);
		employee2.addLists(project3);

		employee3.addLists(project);
		employee3.addLists(project2);
		employee3.addLists(project3);

		entityTransaction.commit();

		entityManager.close();
		entityManagerFactory.close();
		
		

	}
}

Ornegimizi calistirdigimizda 3 tablo olusacaktir , eger mappedBy kullanmasaydik bu durumda 2 tane unidirectional ManyToMany iliski olacakti ve 4 tane tablo olusacakti.

manytomany bidirectional

NOT : Ornekleri calistirirken oncesinde tablolari tamamen temizleyin.
MySQL icin foreign key drop table icin problem olmamasi icin su sql ifadesini calistirin.

SET FOREIGN_KEY_CHECKS = 0

Oracle icin de tablolari rahat sekilde drop etmek icin ;

select 'drop table '||table_name||' cascade constraints;' from user_tables;

Sorgusunu calistirip(F5 ile ) , drop table komutlarini copy-paste ile alip calistiralim ve tum tablolari silelim.

Kaynak kodlar : Injavawetrust.jpa_v9

Yazimi burada sonlandiriyorum.
Herkese Bol Javali Gunler dilerim.
Be an oracle man , import java.*;
Levent Erguder
OCP, Java SE 6 Programmer
OCE, Java EE 6 Web Component Developer

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *