Java Persistence Api (JPA ile programlama) -1
Merhaba arkadaslar ;
Oncelikle nesne-ilişkisel uymsuzluğunu ele alıp hızlıca tarihi olarak bu uyumsuzluğu gidermek için ortaya çıkan çözümlerden bahsedeceğiz cunku bu uyumsuzluk yuzunden JPA ortaya cikmistir. Bu yuzden ilk once kod yazmaktansa edebi kismina biraz kafa yoralim hersey kolaylasacaktir .
J2EE ‘de bir uygulama gelistirdigimizde sınıflar/nesneler ile aralarındaki ilişkilerin ifade ediliş şekli, iliskisel veritabanindaki tablolar ve aralarındaki ilişkilerin ifade edilişinden pek çok bakımdan farklılık arzeder. Bu iki sistem, kapsülleme (encapsulation), tip, erişim, güvenlik vb. pek çok temel konuda, değişik çıkış noktalarına sahip olmalarından dolayı, farklı yaklaşımlar benimsemişlerdir. Bu durum nesne-ilişkisel uyumsuzluğu (object-relational mismatch) olarak adlandırılır.Nesnelerin tablolarda kalıcı hale getirilmeleri için uygulamadaki sınıfların veri tabanındaki tablolara, sınıflarda tanımlanan nesne özelliklerinin yani nesne değişkenlerinin (instance/object variables) de bu tablolardaki sütunlarla/kolonlarla eşleştirilmesi gerekmektedir. Buna da “nesne-ilişkisel eşleştirme” (Object-Relational Mapping, ORM) denir.
Nesne-merkezli diller ile geliştirilen uygulamalarda nesne-ilişkisel uyumsuzluğunu tekrar tekrar yaşayan programcıların bu problemi aşmak için geliştirdikleri çözüm iliskisel veritabanini ile uygulama arasına konulacak böyle bir katmanın iki arayüzü olacaktır: Birisi SQL’ı kullanarak iliskisel veritabani ile haberleşen arayüz, diğeri ise bir API üzerinden nesnelerle alakalı business methods işlemlerini ( reate, read, update, delete ) yapmaya izin veren arayüz. Dolayısıyla bu katman, uygulama programcılarını, arkadaki veritabaninin ilişikisel yapısından uzak tutacak ve onlara, nesneleri sanki OODBMS ( object-oriented database management system) kalıcı kılıyormuş gibi program yazma imkanı sağlayacaktır.
Hibernate ,TopLink vs yukarda anlattigimiz gibi katmanlar , API’lere sahiptiler ama bundan dolayida problemler ortaya cikti hepsinin farklı bir yaklaşıma dolayısıyla da bir API’ye sahip olmalarıydı. Bu yüzden bu çözümler birbirlerinin yerine geçebilir durumda değillerdi. Bu süreçte Sun, bu problemine bir başka çözüm önermek üzere yola çıktı ve eski tecrübeleri ile Toplink ve Hibernate gibi başarılı araçların birikimlerini bir araya getirerek JPA (Java Persistence API) isimli yeni bir bileşen yayınladı. Ana teması “daha kolay geliştirme” olan Java EE 5’in içindeki EJB 3.0’ın bir parçası olarak 2006 yılında Javacılara sunulan JPA 1.0, büyük bir ilgiyle karşılalandı.
JPA nin dogusunu anladiktan sonra Entity nedir buna bakalim .Entity’i şu blogda (Akin Kaldiroglu) güzel bir şekilde anlatmış oradan alıntı yapalım.
Entity
JPA’yı kullanarak veri tabanında kalıcı kılınacak olan nesneye entity denir. Bir nesnenin entity olması için gerek ve yeter şart o nesnenin kendisinden üretileceği sınıfın @Entity olarak ifade edilmesidir. Entity bir iç sınıf (inner class), bir interface ya da enum tipi veya final olmamalıdır ve public ya da protected olan bir argumansız yapılandırıcısı (no-arg constructor) olmalıdır.
Entitynin veri tabanında saklanancak olan kalıcı durumu (persistent state), tamamen nesne değişkenlerinden oluşacaktır. Bu yüzden kalıcı durumun parçası olacak nesne değişkenleri final olmamalıdır. Nesne değişkenleri private olabilir hatta olmalıdır ve kalıcı olan nesnenin istemcileri (client), nesnenin değişkenlerine get/set metotları ile ulaşmalıdır. Entitylerin kalıcılığının minimum sayıda alandan (nesne değişkeni) oluşması gerektiği düşünüldüğünde, veri tabanında kalıcı olması gerekmeyen değişkenler @Transient ile notlandırılmasının gerekir.
Bir sınıfın entity olması için teorik olarak zorunlu olmamakla birlikte konulmadığında pratikte pek çok sıkıntı çıkardığı için gerekli olarak belirttiğimiz bir diğer not ise @Id’dir. Bu not, notlandırdığı alanın, içinde bulunduğu nesnenin kimlik (identity) bilgisini ifade etmesini ve veri tabanında da bir anahtar alana (primary key) karşı gelmesini sağlamaktadır.
Yukarıdaki bilgiler ışığında aşağıdaki gibi bir sınıf JPA tarafından veri tabanında kalıcı hale getirilecektir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
package tr.memo.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; /** * * @author MehmetKilic (www.turkishh.com) */ @Entity(name="FIRMA") public class Firma implements java.io.Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name="ID") private long id; @Column(name="FIRMA_NAME",length=255 ,nullable=true , unique=false) private String firmaName; @Column(name="TELEFON") private String telefon; @Column(name="ADRES") private String adres; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getAdres() { return adres; } public void setAdres(String adres) { this.adres = adres; } public String getFirmaName() { return firmaName; } public void setFirmaName(String firmaName) { this.firmaName = firmaName; } public String getTelefon() { return telefon; } public void setTelefon(String telefon) { this.telefon = telefon; } } |
yukarda gordugunuz gbi biz normal java sinifi olusturduk ama iliskisel veritabanimiza bir tablo yaratmis gibi olduk tablo ismi verdik kolon isimleri vs hepsini atadik . Bunlari yukarida anlattigim gibi katman veya API olusturmak zorunda kalmadik isimizi birkac annotation yazarak hallettik.
JPA, bir JPA ürünü ve kullanılacak veri tabanıyla ilgili olarak yapılacak ayarları classpathde META-INF klasörünün altında persistence.xml isimli bir dosyada olmasını bekler. Biz de projemizde böyle bir dosya oluşturup içine Hibernate ve kullanacağımız veri tabanıyla alakalı en temel bilgileri aşağıdaki gibi verebiliriz:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="KiliclarJPU1" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>tr.memo.entity.Firma</class> <class>tr.memo.entity.SatilanUrunler</class> <class>tr.memo.entity.UrunAlinan</class> <class>tr.memo.entity.UrunSatilan</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/kiliclar"/> <property name="javax.persistence.jdbc.password" value="turkishh"/> <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/> <property name="javax.persistence.jdbc.user" value="turkishh"/> <property name="eclipselink.ddl-generation" value="create-tables"/> </properties> </persistence-unit> </persistence> |
1 |
1 |
<persistence-unit name="KiliclarJPU1" transaction-type="RESOURCE_LOCAL"> |
Tanımladığımız bu kalıcılık biriminin işlem (transaction) tipi ise “RESOURCE_LOCAL” olarak verilmiş durumda. “RESOURCE_LOCAL” işlem tipi, JPA’in işlemleri herhangi bir JTA altyapısı kullanmadan yöneteceğini ifade eder. Bu tipin alternatifi “JTA”dir ve bu durumda JPA kullanabileceği bir JTA ürünü arar ki en temelde böyle bir durum, bir uygulama sunucusunun varlığı halinde kullanılır. Biz bu yazımızda JPA’in sadece Java SE ortamında nasıl kullanıldığınından bahsedeceğimiz için işlem tipimiz daima “RESOURCE_LOCAL” olacaktır.
1 2 3 4 |
<class>tr.memo.entity.Firma</class> <class>tr.memo.entity.SatilanUrunler</class> <class>tr.memo.entity.UrunAlinan</class> <class>tr.memo.entity.UrunSatilan</class> |
1 |
Yukarida gordugunuz gibi olusturdugumuz classlarimiz . |
1 |
Iliskisel vertabani URL'i |
1 |
<property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/kiliclar"/> |
1 |
Iliskisel vertabani password |
1 |
<property name="javax.persistence.jdbc.password" value="turkishh"/> |
1 |
Iliskisel vertabanina ait olan driver |
1 |
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/> |
1 |
Iliskisel vertabani username |
1 |
<property name="javax.persistence.jdbc.user" value="turkishh"/> |
1 |
Iliskisel vertabani olusturulmasi |
1 |
<property name="eclipselink.ddl-generation" value="create-tables"/> |
1 |
Artik tablolarimiz olusturulduguna gore entity manager ile kucuk testler yapalim zaten tum database islemlerini onun sayesinde yapacagiz (create , update ,delete vs)
EntityManager
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public class Test { EntityManagerFactory emf = Persistence.createEntityManagerFactory("KiliclarJPU1"); EntityManager em = emf.createEntityManager(); public void createFirma(Firma firma) { em.getTransaction().begin(); em.persist(firma); em.getTransaction().commit(); } public void updateFirma(Firma firma) { em.getTransaction().begin(); em.merge(firma); em.getTransaction().commit(); } public void removeFirma(Firma firma) { em.getTransaction().begin(); em.remove(em.merge(firma)); em.flush(); em.getTransaction().commit(); } public List<Firma> getFirmaList() { return em.createQuery("SELECT f FROM Firma f").getResultList(); } } |
simdi arkadaslar su yazdigimiz iki satira dikkat;
1 2 |
EntityManagerFactory emf = Persistence.createEntityManagerFactory("KiliclarJPU1"); EntityManager em = emf.createEntityManager(); |
KiliclarJPU1 isminde name yazmisiz simdi yukari cikarak persistence.xml dosyanisin persistence-unit name ile ayni olmasi lazimdir cunku database hangisi oldugunu anlamaz ve exception firlatir..
1 2 |
Olusturdugumuz methodlara bakilacak olursa Transaction acip kapatmisiz database de commit yapmamiz gerektiginde bunu yapmaliyiz. Methodlardan anlayacaginiz gibi databaseye insert yaptigimizda bunun yerine JPA da persist methodunu cagirarak insert islemini merge yaparak update islemini remove methodunu yazarak delete islemini yapabiliyoruz .. |
1 |
1 |
Uygulamamizda firmalarin listini almak istedigimizde olay biraz degisiyor araya JPQL (Java Persistence Query Language ) giriyor.. |
1 2 3 |
public List<Firma> getFirmaList() { return em.createQuery("SELECT f FROM Firma f").getResultList(); } |
1 |
1 |
normal sql den fazla farki yoktur |
SELECT f FROM Firma f bu syntax’da kullanilmasinda ki amac f degiskeni atamislar oraya mesela f.firs_name seklinde daha esnek bir yapida bilgiyi cekebiliyoruz JPQL de basli basina bir konu insallah onumuzdeki yazimda ona deginecek saglicakla kalin ..
Umarim faydali olmustur
😉
1 |
Mehmet KILIC |
1 Response
[…] http://www.turkishh.com/programlama/java-persistence-api-jpa-ile-programlama-1/ […]