ORM ve JPA Kavramları

Önceki yazılarda Java‘dan ve Object Oriented Programlamadan yeterince bahsedildiğini düşünüyorum. Bu konularda örnek uygulamalar geliştirdikçe etkinliğiniz artacaktır. Önemli olan kavramları ve mantıklarını iyi oturtmuş olmak. Buraya kadar olan bilgiler belki lisans eğitiminizde işinize yarayacaktır ancak daha sonrası için kesinlikle yetersiz. Bu yüzden daha advance konulara giriş yapmak gerektiğini düşündüm. Bu yazıda Object Relational Mapping‘den bahsediyor olacağız. JPA‘nın nasıl oluştuğuna ve ne işe yaradığına değineceğiz. Bundan sonraki yazılarda da Java için en populer ORM uygulaması olan Hibernate üzerinden gitmeyi planlıyorum. Umarım yararlı olacaktır.

Persistence Ne Demektir?

  • Persistence kelime anlamıyla süreklilik, kalıcılık gibi anlamlara gelir.
  • Object oriented programlamada sürekli ve kalıcı olması istenen birimler genelde objectlerdir.
  • İşte bu iki cümle ile persistence için en basit tanım oluşur; yazılımda kullanılan objectlerin kalıcı hale getirilmesine persistence denir.

Yani yazılımınız kapansa bile bu objectler saklanacak ve tekrar açıldığında kullanılmaya hazır olacaktır. Bunu sağlamak için kullanılan yöntemlere ayrıntısıyla değinmeden önce kabaca nasıl sağlandığını anlatalım;

Yazılımınızdan bağımsız bir depolama ünitesi seçiyorsunuz, buna persistence storage deniyor. Persistence storage bir dosya olabildiği gibi ilişkisel bir veritabanı hatta flash ram’in kendisi bile olabiliyor. Uygulamanız içerisinde oluşturduğunuz objectlerinizi persistence storage’e kaydediyorsunuz. Buna persist etmek diyoruz. Daha sonra istediğiniz zaman buradan çekerek kullanıyorsunuz. Buna da load etmek diyoruz. Persist edilen bir nesne program kapanıp tekrar açılsa bile load edilebiliyor.

Bu noktada basit bir örnek verelim. Aşağıdaki gibi bir veritabanı tablonuz olduğunu varsayın, PERSONEL tablosu olsun;

tablo

Böyle bir tabloyu uygulamanızda bir object ile karşıladığınızı düşünün. Bu object tam olarak bu tabloyu temsil edecektir, aslında doğru tabir, “bu tablo tam olarak bu objecti temsil edecektir” şeklinde olmalı. Yukarıdaki tabloya karşılık gelen Calisan isimli sınıfı yazalım;

@Entity
@Table (name = 'PERSONEL')
public class Calisan {

	@Id
	@Column (name = 'TCKN')
	private Long kimlikNo;

	@Column (name = 'NAME')
	private String ad;

	@Column (name = 'SALARY')
	private Number maas;

	@ManyToOne
	@JoinColumn (name = 'DEPARTMENT_ID')
	private Birim birim;

	/*GETTER VE SETTER METHODLARI*/

	public Long getKimlikNo() {
		return kimlikNo;
	}

	public void setKimlikNo(Long kimlikNo) {
		this.kimlikNo = kimlikNo;
	}

	public String getAd() {
		return ad;
	}

	public void setAd(String ad) {
		this.ad = ad;
	}

	public Number getMaas() {
		return maas;
	}

	public void setMaas(Number maas) {
		this.maas = maas;
	}

	public Birim getBirim() {
		return birim;
	}

	public void setBirim(Birim birim) {
		this.birim = birim;
	}
}

Örnek kod için Getter ve Setter methodlarını boşverebiliriniz, @ ile başlayan şeyler de şuanda yabancı geliyor olabilir. Onlara annotation deniyor ve bir sonraki başlıkta ne için kullanıldıklarını anlatacağım. Şimdilik daha fazlasını düşünmeyin ve kafanızı bunlarla karıştırmayın, odaklanmanızı istediğim nokta yazdığınız java sınıfı ile tablonun eşleşmesidir. Gördüğünüz gibi birebir karşılıyor.

PERSONEL tablosu ile Calisan sınıfı arasındaki ilişkiye benzer bir ilişki de tablodaki DEPARTMENT_ID alanının foreign key olduğu DEPARTMENT tablosu ile Calisan sınıfında property olarak bulunan Birim sınıfı arasında vardır. Bu örnekler ile en basit haliyle persistence konusuna girmiş oluruz sanırım 🙂

Peki ORM Nedir?

Persistence kavramını anladıktan sonra akla gelen ilk soru bunun nasıl gerçekleştirildiğidir. Bir objecti persist edebilmek için uygulama katmanınızdaki object model ile storage katmanındaki data modelin eşleştirilmesi gerekir. Persistence işlemi bu eşleştirmeye uygun olarak object modelin data modele dönüştürülmesi şeklinde gerçekleşir. İşte bu eşleştirmeye object relational mapping (ORM) denir.

Bu noktaya kadar persistence storage şeklinde bahsedilen yapıyı bu noktadan sonra ilişkisel veritabanı olarak adlandıracağım. Persistence storage’in veritabanı dışında bir yapı da olabileceğini belirtmek için böyle söylemiştim fakat büyük projelerde her zaman bu yapı ilişkisel veya object oriented bir veritabanı olarak karşımıza çıkmaktadır. Genelde hiçbir büyük projede file system veya flash ram üzerine persistence yapılmaz. Bu konuyu netleştirdikten sonra kaldığımız yerden devam edebiliriz.

ORM kendi başına sadece bir kavram olsa da, bunu gerçeklememizi sağlayan birçok araç bulunmaktadır. Bu araçların genel özellikleri şöyledir;

1. Mapping: ORM araçlarının temel özelliğidir, zaten yukarıda ORM tanımında da mapping’den bahsedilmiştir. Ne olduğu yukarıda anlatıldığı için burada nasıl gerçekleştirildiğinden bahsedilecektir.

Mapping işlemi genel olarak metadata kullanılarak yapılmaktadır. Hibernate aracı için annotation tabanlı metadatalar kullanılırken bazı araçlarda XML tabanlı metadata kullanıldığı bilinmektedir. Persistence başlığında örnek olarak verdiğimiz Calisan sınıfında @ ile başlayan keyword’ler Hibernate annotation‘larıdır.  Mapping yapılırken;

  • Class’lar ile Tablolar
  • Property’ler ile Kolonlar
  • Relation’lar ile Foreign Key’ler
  • Primitive Tipler ile SQL Tipleri

eşleştirilir. Bu eşleştirmeler ileride örneklendirdikçe daha iyi anlaşılacaktır.

2. Persistence: ORM araçlarının genel özelliklerinden biride persistence işlemlerini gerçekleştirmeleridir. Hibernate uygulama katmanı ile veritabanı katmanı arasında durur (DAO Katmanı). Uygulama katmanında çalışan biz yazılımcıları db ile ilgili işlemlerden kurtarır ve bussiness logic’e odaklanmamızı sağlar.

Yazılımcı uygulama katmanında bir object oluşturduğunda ORM aracı sayesinde ilgili veritabanı tablosuna da bir satır eklenir, sildiğinde silinir, güncellediğinde güncellenir. Primary key kullanılarak ilgili satır ilişkili object’e yüklenebilir. Tüm bunlar ORM araçlarının persistence özelliğidir.

3. Query: Birçok ORM aracı veritabanı sorguları için sizi SQL yazmaktan kurtarır. Hibernate’in HQL‘i buna bir örnektir. Aracın sorgulama kütüphaneleri sayesinde SQL yazmadan oldukça karışık sorgular üretebilir ve kullanabilirsiniz. Ayrıca sadece sorgulama için hazırlanmış farklı kütüphaneleride ORM araçları ile birlikte kullanabilirsiniz. Tüm bunlara rağmen birçok ORM aracı Native SQL yazabilmenizi de kısıtlamaz. Klasik yöntemi halen kullanabilirsiniz.

JPA Ne İş Yapar?

Yazılım dünyasına persistence kavramı girdiği andan itibaren gündeme oturmuş ve hızla yaygınlaşmıştır. Doğal olarak Java dünyası da aynı tepkiyi vermiş ve bu konu ile ilgili birçok çalışma yapılmış, sonuç olarak ortaya birçok araç çıkmıştır. Bu araçlardan en ünlüleri yukarıda birkaç kez bahsettiğim ve bundan sonraki yazılarda üzerinde duracağım Hibernate, daha sonra TopLink, Eclipse-Link vb. şeklindedir. Bu araçlar ORM araçlarıdır ve amaçları persistence işlemlerini gerçekleştirmektir.

Bu konuda bu kadar çok kütüphane çıktıktan sonra ortada bir karmaşa oluştu denebilir. Zamanla en iyi olanlar daha çok kullanılmaya başlanmıştır. Ve Java dünyasında her konuda olduğu gibi bu konuda da üretilen bunca kütüphanenin ortak ve iyi yönleri toplanmış ve bir standart belirlenmiştir. İşte bu spesifikasyona Java Persistence API (JPA) denmiştir. API’nin ne olduğunu daha önce anlatmıştım, yani var olan tüm persistence araçlarının standart bir arayüzüdür.

Bu açıklamayı biraz daha basitleştirmeye çalışayım. Birçok persistence aracı olduğunu söylemiştim. Bu araçların kullanımlarının tamamen birbirinden farklı olduğunu düşünün. Hepsinin nasıl kullanıldığını öğrenmek son derece zor ve uğraştırıcıdır. İşte bu durumda araya hepsinin nasıl kullanabileceğini bilen birini alıyorsunuz. Siz sadece o kişiye git şu aracı kullanarak şu veritabanına şu veriyi kaydet diyorsunuz, o da gidip yapıyor. Geri kalanı da sizi ilgilendirmiyor. JPA işlerinizi bu şekilde kolaylaştırıyor.