EclipseLink – 10 – Relationship – 04 – One To Many

Merhaba arkadaslar
Bu bolumde Collection – Valued Relationship konusunu inceleyecegiz. Collection – Valued ozelligi gosteren iliskiler OneToMany ve ManyToMany iliskilerdir. Bu bolumde Bidirectional OneToMany ve Unidirectional OneToMany iliskileri inceleyecegiz.

Collection – Valued Relationships

Bir iliskide target(hedef) cardinality(nicelik) Many ise bu durumda iliski Collection – Valued ozellige sahiptir.
Bu durumda OneToMany ve ManyToMany iliskiler Collection – Valued ozelligine sahiptir.

One To Many Mapping

Onceki bolumde Employee ve Department arasinda ManyToOne bir iliski oldugundan bahsettik. Bu iliskinin Many tarafini Employee One tarafini ise Department olusturmaktaydi.

Bidirectional One To Many Relationship
Bidirectional OneToMany bir iliskiden bahsedebilmek icin bu iliskinin bir tarafi OneToMany diger tarafi ise ManyToOne olmasi gereklidir.

ManyToOne acisindan baktigimizda Employee sinifimizda Department sinifi tipinde bir instance variable/field kullanmamiz yeterli olmaktadir.

OneToMany acisindan baktigimizda bu durumda Department sinifimizda Employee sinifi tipinde bir instance variable/field yeterli olacak midir ? Dusundugumuzde bunun yaniti hayir olacaktir. Bir Department icin birden fazla Employee soz konusu oldugu icin bu durumda bir java.util.Collection kullanmamiz gereklidir.

bidirectional onetomany relationship

Employee17.java

package _17.oneToMany.bi.model;

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

@Entity
public class Employee17 {

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

	@ManyToOne
	@JoinColumn(name = "DEPT_ID")
	private Department2 department;

       //constructors
       //getters and setters
       //toString


}

Employee17 sinifimizda @ManyToOne annotation kullaniyoruz. @JoinColumn , owning side/iliski sahibi tarafinda kullanilir. ManyToOne//OneToMany bidirectional iliski soz konusu oldugunda owning side her zaman Many tarafidir.

Department2.java

package _17.oneToMany.bi.model;

import java.util.ArrayList;
import java.util.Collection;

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

@Entity
public class Department2 {

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

	@OneToMany(mappedBy = "department")
	private Collection<Employee17> employees;

	// Collection taniminda generic yapi kullanilmazsa bu durumda @OneToMany
	// annotation'da targetEntity parametresi kullanilmalidir.
	// @OneToMany(targetEntity=Employee17.class)
	// private Collection employees;

	//constructors
        //getters and setters
        //toString

}

mappedBy parametresini Department2 sinifimizda kullaniyoruz. Bidirectional OneToMany/ManyToOne bir iliski icin inverse side her zaman One tarafidir.
Bidirectional OneToMany/ManyToOne bir iliskide mappedBy inverse side’a eklenir.
Bunun anlami Employee17 Entity’si bu iliskinin sahibidir , owning side. Foreign key bilgisi bu durumda Employee17 tablosunda yer almaktadir.

Collection taniminda generic yapi kullanilmazsa bu durumda @OneToMany annotation’da targetEntity parametresi kullanilmalidir.

OneToOne iliskiyi incelerken bahsetmistik , bidirectional bir iliski de olsa mutlaka karsilikli olarak ilgili set metotlarini cagirmamiz gereklidir. Benzer sekilde burada da ayni durum soz konusudur.

EmployeeTest.java

....
	entityTransaction.begin();
	
	employee.setDepartment(department);
	department.getEmployees().add(employee);

	employee2.setDepartment(department2);
	department2.getEmployees().add(employee2);

	employee3.setDepartment(department2);
	department2.getEmployees().add(employee3);

	entityTransaction.commit();
....

setDeparment metodunu kullandiktan sonra Collection yapimiza employee objesini ekliyoruz. Dikkat edecek herhangi bir yerde new anahtar kelimesini kullanmadik. EclipseLink kullandigimizda  org.eclipse.persistence.indirection.IndirectList sinifi tipinde bir obje olusacaktir.

public class IndirectList extends Vector implements CollectionChangeTracker, IndirectCollection {...}

Hibernate icin test edersek bu durumda java.lang.NullPointerException hatasi aliriz.
Bu nedenle kullandigimiz yapilandiricida ArrayList objesi olusturabiliriz.

	public Department2(String name) {
		super();
		this.name = name;
		employees= new ArrayList();
	}

findDepartment metodunu kullanarak id degerine gore ilgili kayit tablodan getirilir. getEmployees metodu ile Department objesine ekledigimiz Employee objeleri gelecektir.

Department2 foundDepartment = departmentService.findDepartment(5);
	if (foundDepartment != null) {
	    Collection<Employee17> employees = foundDepartment.getEmployees();
	    System.out.println(employees);
	}

Ornegimizi calistirdigimizda Employee17 ve Department2 tablomuz ;

employee department onetomany manytoone bidirectional

Unidirectional One To Many Relationship
Sadece @OneToMany annotation kullanildigi durumda iliski unidirectional olacaktir. Ornek olarak Employee ve Phone Entity’lerini dusunebiliriz. Employee ait birden fazla telefon numarasi olabilir , bir telefon sadece bir calisana ait olacaktir. Bu durumda Employee sinifinda elemanlari Phone objesi olan Collection tanimlanmalidir.

Bidirectional OneToMany/ManyToOne iliskide mappedBy parametresi OneToMany tarafinda yer almalidir. Unidirectional iliskilerde mappedBy parametresi kullanilmaz , mappedBy parametresinden bahsedebilmek icin iliski Bidirectional olmalidir.

Unidirectional OneToMany bir iliskide owning side One tarafidir. One tarafi Employee Many tarafi Phone olacak.

employee phone onetomany

Phone.java

package _18.oneToMany.uni.model;

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

@Entity
public class Phone {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private int id;
    private String no;
    //number oracle icin
    private String type;
    
    //constructor
    //getters and setter
    //toString   
}

Employee18.java

package _18.oneToMany.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.OneToMany;

@Entity
public class Employee18 {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private int id;
    private String name;
    private String surname;
    private int salary;
    @OneToMany
    private List<Phone> phones;

    //constructors
    //getters and setter
    //toString

}

Employee18 sinifimizda @OneToMany annotation kullaniyoruz. Elemanlari Phone olan bir List tanimladik.

EmployeeTest.java

package _18.oneTomany.uni.test;


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

import _18.oneToMany.uni.model.Employee18;
import _18.oneToMany.uni.model.Phone;
import _18.oneToMany.uni.service.EmployeeService;
import _18.oneToMany.uni.service.EmployeeServiceImpl;
import _18.oneToMany.uni.service.PhoneService;
import _18.oneToMany.uni.service.PhoneServiceImpl;

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();
	Employee18 employee = employeeService.createEmployee("Levent", "Erguder", 1000);
	entityTransaction.commit();

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

	PhoneService phoneService = new PhoneServiceImpl(entityManager);

	entityTransaction.begin();
	Phone phone = phoneService.createPhone("0555", "Mobile");
	Phone phone2 = phoneService.createPhone("216", "Home");
	Phone phone3 = phoneService.createPhone("212", "Work");
	entityTransaction.commit();

	System.out.println("Persisted :" + phone);
	System.out.println("Persisted :" + phone2);
	System.out.println("Persisted :" + phone3);

	entityTransaction.begin();
	employee.getPhones().add(phone);
	employee.getPhones().add(phone2);
	employee.getPhones().add(phone3);
	entityTransaction.commit();

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

    }
}

Ornegimizi incelersek , Employee objemizi olusturduktan sonra 3 tane Phone objesi olusturuyoruz. Phone objelerini List’e ekliyoruz.

Ornegimizi calistirdigimizda 3 tane tablo olusacaktir !  Dikkat edecek olursak Employee18_Phone tablosunda id bilgileri yer alacaktir.

employee phone onetomany unidirectional

Varsayilan olaran Unidirectional OneToMany bir iliski icin 3.tablo olusacaktir.
Olusan bu tablo icin isim 2 Entity’in isimlerinin birlesimi olacaktir.
Dolayisiyla tablo ismi Employee18 ve Phone tablolarinin isimlerinin birlesimi olacaktir.
Owning side ismi ile baslar dolayisiyla Employee18_Phone seklinde olacaktir.
Kolon isimleri Employee18_id , owning side tablo adi _ id ,
Phones_Id , Employee18 sinifimizdaki List<Phone> phones instance variable isminden gelmektedir.

Varsayilan bu table/column isimlerini degistirmek icin @JoinTable annotation’i kullanabiliriz.

	@OneToMany
	@JoinTable(name = "EMP_PHONE", 
		joinColumns = @JoinColumn(name = "EMP_ID"), 
		inverseJoinColumns = @JoinColumn(name = "PHN_ID"))
	private List phones;

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

@OneToMany annotation’i ekstra tablo olmadan da kullanabiliriz. Bunun icin @JoinTable annotation yerine @JoinColumn annotation’i kullanabiliriz.

	@JoinColumn(name="PHN_ID")
	private List phones;

onetomany jointable

@JoinTable annotation da belirtigimiz name parametre degerine gore EMP_PHONE tablomuz olustu. Kolon isimleri de joinColumns ve inverseJoinColumns parametresinde belirtigimiz gibi EMP_ID ve PHN_ID

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_v8

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 *