EclipseLink – 03 – Accessing Entity State

Merhaba Arkadaslar
Bu bolumde Field Access , Property Access ve Mixed Access konularini inceleyecegiz. Her biriyle ilgili ornek yapacagiz.

JPA Persistence Annotations

JPA’da kullanacagimiz annotation’lar 3 farkli yerde/seviyede tanimlanabilir. Annotation’lar code tanimlarindan once gelmelidir.

Annotation’lari tanimlabilecegimiz yerler su tanimlarin oncesidir ;

  • class
  • method
  • field/instance variable

JPA Annotation’lari okunabilir (readable) , esnek (flexible) , kolay kullanim (easy to specify) ozelliklerine sahip olacak sekilde tasarlanmistir.

JPA Annotation’larini 2 kategoriye ayirabiliriz ;

  • Logical (Mantiksal) Annotation
  • Physical (Fiziksel) Annotation

Logical Annotation’lar Entity’ler arasindaki class associations (sinif iliskileri) icin ,
Physical Annotation’lar , schema , table , column , constraints vs icin kullanacagimiz annotation’lardir.

Accessing Entity State

Entity state’e calisma zamaninda (runtime) ulasim saglamak icin 2 fakli annotation yaklasimi kullanilir.

  • Field(instance variable) Annotation
  • JavaBean style Properties Annotation

Field Access
Field Access yaklasimi kullanildiginda Annotation’lar field/instance variable uzerinde yer alir. JPA Spec’tine field’ler/instance variable private, protected ya da default/package level olabilir public olamaz fakat EclipseLink bu kurala da uymaz public olarak tanimlanabilir tabi onceki yazida belirttigim JPA Validation aktif olmasi durumu ve sarti ile.

Field Access yaklasimi kullanildiginda getter/setter metodu zorunlu degildir. Instance variable uzerinden Entity durumu set/get islemine tabi tutulur. Tabi Object Oriented yaklasimi dusundugumuzde Encapsulation’a uygun olarak private degiskenler tanimlariz ve public getter setter metotlar kullaniriz.

Ilk ornegimizi field access ile yapmistik. Ayni ornegi kisaca hatirlayacak olursak ;

Employee2.java

package _02.field.access.model;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Employee2 {

	@Id
	// field access
	private int id;
	private String name;
	private String surname;
	private int salary;

	public Employee2() {
		super();
	}

	public Employee2(int id, String name, String surname, int salary) {
		super();
		this.id = id;
		this.name = name;
		this.surname = surname;
		this.salary = salary;
	}

	//getters and setters
}

EmployeeService , EmployeeServiceImpl ve EmployeeTest siniflarimizi basitlestirip kullaniyoruz. Yazinin sonunda ornek kodu indirdiginizde ilgili pakette bu siniflari da gorebilirsiniz.

Farkli pakette olmasina ragmen neden Employee2 dedik ? Bunun nedeni ayni Persistence Unit icin Entity ismi unique/essiz olmalidir.

Orneklerimizde Employee2 , Employee3 seklinde sinif isimlarimiz devam edecektir.

persistence.xml dosyamiza etiketini kullanarak yeni ekledigimiz Employee2 sinifimizi bildirelim.

persistence.xml

<class>_02.field.access.model.Employee2</class>

Property Access
Property Access yaklasiminda getter/setter metot tanimlanmak zorundadir. Bu getter/setter metotlar public ya da protected olmalidir.
Annotation getter metodu uzerine yazilir , setter metodu uzerinde annotation tanimlamak gecerli degildir!
Getter/Setter metotlarinin isimleri JavaBean convention kuralina uygun olmalidir.

Getter/Setter metotlar uzerinden Entity durumu set/get islemine tabi tutulur. Field Access’ler farkini gorebilmek icin getter/setter metotlarina debug koyabilirsiniz. Field Access’te getter/setter metotlari kullanilmaz , Property Access’te ise getter/setter metotlari kullanilir.

Property tipi T olsun , ismi x olsun . Bu durumda getter/setter metotlar

T getX()
void setX(T t)

Getter metot icin ; eger degisken tipi boolean degilse , on ek get olmali. Eger degisken boolean ise , get veya is olabilir.

Employee3.java

package _03.property.access.model;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Employee3 {

	private int id;
	private String name;
	private String surname;
	private int salary;

	public Employee3() {
		super();
	}

	public Employee3(int id, String name, String surname, int salary) {
		super();
		this.id = id;
		this.name = name;
		this.surname = surname;
		this.salary = salary;
	}

	@Id
	// property access!
	// @Id annotation getter metot uzerinde olmalidir. setter metot uzerinde
	// tanimlamak gecerli degildir.
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	//getter setter

}

Not : Burada onemli nokta getter ve setter metot ismidir. Java gelistiricileri olarak getter/setter metotlarini otomatik olarak olusturuyoruz. Kullanilan IDE de JavaBean convention’a gore getter/setter metodu olusturmaktadir.

Ornegin ; getNameX ve setNameX seklinde setter/getter metotlarini tanimlarsak veritabaninda tablomuzda Name yerine NameX olacaktir.

persistence.xml

<class>_03.property.access.model.Employee3</class>

Mixed Access

Varsayilan olarak Field Access ya da Property Access bir Entity icin gecerli olacaktir.
Field Access ve Property Access’i birlikte kullanabiliriz. Bu durum cok fazla tercih edilen kullanilan bir yontem degildir fakat bazi noktalarda kullanisli olabilir.

Field Access ve Property Access’i birlikte kullanabilmek icin @Access annotation’indan yararlaniriz.

Ornegin veritabanina yazma ve okuma isleminde data/veri uzerinde degisiklik yapabiliriz.
Employee entity varsayilan olarak Field Access kullansin. Ornegin mobilePhone attribute’u icin bir veri degisikligi yapmak istiyoruz.

Aciklamalari kod icerisinde bulabilirsiniz ;

Employee4.java

package _04.mixed.access.model;

import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;

@Entity
@Access(AccessType.FIELD)
// Field Access ve Property access beraber kullanmak icin @Access annotation
// kullanmamiz gereklidir.
// Entity imiz AccessType olarak FIELD (instance variable) kullansin diye
// belirtiyoruz.
// bu durumda getter/setter metotlari degil instance variable Entity State icin
// kullanilir.
public class Employee4 {

	// static degiskenler Entity State icin degerlendirmeye alinmaz , table'da
	// bir column'a karsilik gelmez.
	public static String TURKEY_CODE = "+90";
	public static String USA_CODE = "+1";

	@Id
	private int id;
	private String name;
	private String surname;
	private int salary;
	
	@Transient
	// mobilePhone ve phoneNumberWithCode icin 2 tane column olusacaktir.
	// mobilePhone icin @Transient annotation kullanabiliriz ya da transient
	// olarak tanimlayabiliriz.
	// Bu durumda table'da bu column olusmayacaktir.
	private String mobilephone;

	// private transient String mobilephone;

	public Employee4() {
		super();
	}

	public Employee4(int id, String name, String surname, int salary, String mobilephone) {
		super();
		this.id = id;
		this.name = name;
		this.surname = surname;
		this.salary = salary;
		this.mobilephone = mobilephone;
	}

       //getters and setters

	// phoneNumberWithCode 'e karsilik gelen
	// JavaBean style uygun olarak tanimlanan getter/setter metodumuz.

	// Bu noktada Property Access yaklasimi uyguluyoruz.
	// Bunun icin @Access annotation kullaniyoruz.
	// Entity State icin diger getter/setter metotlar calismayacaktir. Fakat bu
	// noktada Property yaklasimi kullanildigi icin bu metot kullanilacaktir.
	@Access(AccessType.PROPERTY)
	public String getPhoneNumberWithCode() {
		if (mobilephone.startsWith("5")) {
			return TURKEY_CODE + mobilephone;
		} else {
			return USA_CODE + mobilephone;
		}
	}

	public void setPhoneNumberWithCode(String mobilephone) {
		this.mobilephone = mobilephone;
	}

	@Override
	public String toString() {
		return "Employee4 [id=" + id + ", name=" + name + ", surname=" + surname + ", salary=" + salary + ", mobilephone=" + mobilephone + "]";
	}

}

persistence.xml dosyamizin son hali ;

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
	<persistence-unit name="EmployeePersistenceUnit"
		transaction-type="RESOURCE_LOCAL">
		<class>_01.hello.eclipselink.model.Employee</class>
		<class>_02.field.access.model.Employee2</class>
		<class>_03.property.access.model.Employee3</class>
		<class>_04.mixed.access.model.Employee4</class>
		<properties>
			<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
			<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa.schema" />
			<property name="javax.persistence.jdbc.user" value="root" />
			<property name="javax.persistence.jdbc.password" value="" />
			<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
			<property name="eclipselink.logging.level" value="OFF" />
		</properties>
	</persistence-unit>
</persistence>

Digerlerinden biraz daha farkli oldugu icin Mixed Access icin yaptigimiz ornegin ciktisini burada inceleyelim. Diger ornekleri kendiniz test edebilirsiniz.

Run Application

EmployeeTest.java

package _04.mixed.access.test;

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

import _04.mixed.access.model.Employee4;
import _04.mixed.access.service.EmployeeService;
import _04.mixed.access.service.EmployeeServiceImpl;


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();
		Employee4 employee = employeeService.insertEmployee(1, "Levent", "Erguder", 1000,"555 000 00 00");
		Employee4 employee2 = employeeService.insertEmployee(2, "James", "Gosling", 10000,"200 400 50");
		Employee4 employee3 = employeeService.insertEmployee(3, "Joshua", "Bloch", 10000,"300 500 70");
		entityTransaction.commit();

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

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

	}
}

mobilePhone , @Transient olmadigi durumda Employee4 tablomuzda column olusacaktir.

without Transient

@Transient annotation ve/veya transient keyword kullanildigi durumda Employee4 tablomuzda MobilePhone column olusmayacaktir.

with Transient

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 *