Eclipse Juno üzerinde Hibernate Örneği

Kullandığım teknolojiler ve araçlar;

  • JDK 1.7
  • Eclipse Juno 4.2
  • Oracle XE 11g
  • Hibernate 4.2

Yazdığım proje basit bir konsol uygulamasıdır. Hibernate’in son sürümü olan 4.2 ile geliştirilmiştir. Dolayısıyla SessionFactory nesnesi yaratılırken deprecate edilen eski metot yerine yenisi kullanılmıştır.

Öncelikle Eclipse’de yeni bir Java projesi yaratalım. Ben ismine HibernateCRUD dedim. Projemin “Build Path” ine Hibernate’in JAR dosyalarını ekliyorum. Bu işlemi proje üzerinde sağ tıklayarak BuildPath -> Add External Archives.. seçeneği ile gerçekleştirebilirsiniz.

1

Kullandığım JAR listesi aşağıdaki gibidir.

  • Öncelikle buradan indirmiş olduğunuz hibernate-search-4.2.0.Final ZIP dosyasını dilediğiniz bir yere çıkartın. Daha sonra distlibrequired  altındaki tüm JAR’ları ekleyin.
  • İkinci adımda eğer benim gibi annotation kullanacaksanız gereken hibernate-annotations.jar, hibernate-commons-annotations.jar, ejb3-persistence.jar dosyalarını ekleyin. Eğer annotation yerine konfigurasyon dosyaları (*.hbm.xml) kullancaksanız o zaman bu JAR’lara gerek yok. Bu JAR’ları şu adresten indirebilirsiniz.
  • Üçüncü adımda hibernate-search-4.2.0.Final dosyası içerisinden distlibprovided dizini altındaki hibernate-jpa-2.0-api-1.0.1.Final.jar dosyasını ekliyoruz.
  • Son olarak da bağlanacağımız veri tabanının driver’ını ekliyoruz. Ben Oracle kullandığım için ojdbc6.jar  dosyasını da CLASSPATH’ime ekliyorum.

Projemin kullandığı kütüphaneler en son aşağıdaki gibi oluyor.

2

 

Veri tabanımızda halihazırda bulunan örnek tablolardan REGIONS tablosunu kullanacağım. Hibernate’in veri tabanına bağlanabilmesi için gerekli olan konfigurasyon dosyasını yaratıyorum. Kaynak kodlarımın bulunduğu yerde yarattığımın hibernate.cfg.xml dosyası aşağıdaki gibi olacaktır. Eğer siz başka bir veri tabanına bağlanıyorsanız bağlantı ayarlarınızı değiştirmelisiniz.

[codesyntax lang=”xml” lines=”no”]

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory>
		<property name="hibernate.dialect">
			org.hibernate.dialect.OracleDialect
		</property>
		<property name="hibernate.connection.driver_class">
			oracle.jdbc.OracleDriver
		</property>

		<property name="hibernate.connection.url">
			jdbc:oracle:thin:@localhost:1521:xe
		</property>
		<property name="hibernate.connection.username">
			hr
		</property>
		<property name="hibernate.connection.password">
			hr
		</property>

		<!-- List of XML mapping files -->
		<mapping class="com.javauzmani.entities.Regions" />

	</session-factory>
</hibernate-configuration>

[/codesyntax]

Alt yapımızı hazırladıktan sonra şimdi kodu yazmaya başlayalım. Önce veri tabanındaki tabloya karşılık gelen entity sınıfını yaratıyorum.

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.entities;

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

@Entity
public class Regions {

	@Id
	@Column(name = "region_id")
	private int regionId;

	@Column(name = "region_name")
	private String regionName;

	public Regions() {
		super();
	}

	public Regions(int regionId, String regionName) {
		super();
		this.regionId = regionId;
		this.regionName = regionName;
	}

	public int getRegionId() {
		return regionId;
	}

	public void setRegionId(int regionId) {
		this.regionId = regionId;
	}

	public String getRegionName() {
		return regionName;
	}

	public void setRegionName(String regionName) {
		this.regionName = regionName;
	}
}

[/codesyntax]

Daha sonra ekleme, silme, güncelleme ve listeleme işlemlerini yapacak olan sınıfımı yazıyorum.

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.dao;

import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

import com.javauzmani.entities.Regions;

public class RegionsDAO {
	static ServiceRegistry serviceRegistry = null;
	static SessionFactory factory = null;
	static Configuration configuration = null;

	static {
		try {
			configuration = new Configuration().configure("hibernate.cfg.xml");
			serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
			factory = configuration.buildSessionFactory(serviceRegistry);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void addRegions(int regionId, String name) {
		Session session = factory.openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			Regions regions = new Regions(regionId, name);
			session.save(regions);
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	@SuppressWarnings("unchecked")
	public List<Regions> listRegions() {
		Session session = factory.openSession();
		Transaction tx = null;
		List<Regions> regions = null;
		try {
			tx = session.beginTransaction();
			regions = session.createQuery("from Regions").list();
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
		} finally {
			session.close();
		}
		return regions;
	}

	public void updateRegions(Integer regionsId, String regionName) {
		Session session = factory.openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			Regions region = (Regions) session.get(Regions.class, regionsId);
			region.setRegionName(regionName);
			session.update(region);
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	public void deleteRegions(Integer regionsId) {
		Session session = factory.openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			Regions region = (Regions) session.get(Regions.class, regionsId);
			session.delete(region);
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
		} finally {
			session.close();
		}
	}
}

[/codesyntax]

Son olarak da yazmış olduğum DAO sınıfındaki metotları çağıracak örnek bir test sınıfı yaratıyorum.

[codesyntax lang=”java” lines=”no”]

package com.javauzmani.calistir;

import java.util.List;

import com.javauzmani.dao.RegionsDAO;
import com.javauzmani.entities.Regions;

public class CrudDeneme {
	public static void main(String[] args) {

		RegionsDAO dao = new RegionsDAO();
		List<Regions> regions = dao.listRegions();

		for (Regions region : regions) {
			System.out.print("Region Id : " + region.getRegionId());
			System.out.print(", Region Name : " + region.getRegionName());
			System.out.println();
		}
	}
}

[/codesyntax]

[box type=”warning”]Veri tabanı sunucunuzun açık olduğundan emin olunuz !!![/box]

Kodumuzu çalıştırdığımızda çıktı aşağıdaki gibi oluyor.

3

 

Hibernate Mapping Types

Hibernate’te Java sınıflarını veri tabanındaki tablolara eşleştirmek için kullanılan “mapping” dosyalarında tipler karşımıza çıkar. Bu tipler Java tipi ya da SQL tipi değildirler. Bunlar tam olarak Java tiplerini SQL tiplere, SQL tiplerini de Java tiplerine dönüştürmeyi sağlayan Hibernate tipleridir. Örnek bir “mapping” dosyası aşağıdaki gibidir.

Araba.hbm.xml

[codesyntax lang=”xml” lines=”no”]

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
 "-//Hibernate/Hibernate Mapping DTD//EN"
 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name="Araba" table="ARABA">
      <id name="id" type="int" column="id">
         <generator class="native"/>
      </id>
      <property name="marka" column="marka" type="string"/>
      <property name="model" column="model" type="string"/>
      <property name="uretimYili" column="uretim_yili" type="int"/>
   </class>
</hibernate-mapping>

[/codesyntax]

Dönüşümleri sağlayan Hibernate tiplerinin neler olduğu ve hangi dönüşümleri gerçekleştirdiği bilgisinin işinize yarayacağını düşünüyorum.

1 2

Örnek Hibernate Uygulaması

Yarattığımız projeye Hibernate özelliklerini eklemek demek Hibernate’in kullanacağı tüm kütüphaneleri (jar dosyalarını) projemize entegre etmek demektir. Biz de örnek uygulamamızı yazmadan önce Hibernate’in kullandığı tüm kütüphaneleri indirerek uygulamamıza eklemeliyiz. Eğer benim gibi Hibernate’e direk destek veren bir geliştirme ortamı kullanıyorsanız bu kütüphaneleri uygulamaya entegre etmek çok daha basit hale gelecektir. Ben MyEclipse kullanarak Hibernate ile veri tabanı uygulaması yapacağım.

Önce yeni bir Java projesi yaratalım.

Sonra yarattığımız projeye Hibernate kütüphanelerini ekleyelim.

Karşımıza gelen sihirbazda Hibernate’in hangi versiyonunu kullanacağımızı seçtikten sonra annotation’ları kullanacağımızı belirtiyoruz.

Daha sonra veri tabanı bağlantı ayarlarının tutulacağı XML dosyasının adını ve adresini giriyoruz.

Bir sonraki adımda hangi veri tabanına bağlanacaksak o veri tabanının connection url, driver ve kullanıcı adı parola bilgilerini giriyoruz.

Yukarıda anlatmış olduğum session factory sınıfını otomatik olarak yaratmak isteyip istemediğimizi seçiyoruz. Eğer yaratacaksak sınıfın ismini ve bulunacağı paketi seçiyoruz.

En son Finish düğmesine bastığımızda dizin yapısı ve konfigurasyon dosyası aşağıdaki gibi olacaktır.

Bizim için HibernateSessionFacttory sınıfının yanında bir de hibernate.cfg.xml adında bir konfigurasyon dosyası yaratıldı. Bu dosya içerisinde veri tabanı bağlantı ayarları yer alıyor. Hangi veri tabanına bağlanacaksak onun connection url, driver class bilgilerini yazıyoruz.

Hibernate’e destek veren IDE’lerin bir diğer güzel özelliği de reverse engineering denilen otomatik sınıf yaratma işlemlerinin yapılabilmesidir.

Hibernate reverse engineering kullanarak entity ve dao sınıflarını artı hangi sınıfın hangi tabloya karşılık geldiğini belirten konfigurasyon dosyalarını yaratabiliriz ancak ben bu örnekte sadece entity sınıfını yaratacağım. DAO sınıflarını ve her entity sınıfının hangi tabloya karşılık geldiğini belirten XML dosyalarını yaratmayacağım. Bunun yerine annotation’ları kullanacağım.

Entity sınıflarını yaratmak için veri tabanı perspektifine geçerek sınıfını yaratacağım tablonun üzerinde sağ klik Hibernate Reverse Engineering… seçeneğine tıklıyoruz.

Açılan sayfada yaratılacak entity sınıfının paketini belirtiyoruz. Aşağı kısımda ise mapping’in hangi şekilde yapılacağını söylüyoruz. İlk seçeneği seçtiğimizde her bir entity sınıfı için bir de XML konfigurasyon dosyası yaratılır. İkinci seçenekte ise entity sınıfında annotation’lar ile mapping yapılır ki biz bu şekilde yapacağız. Dediğim gibi DAO ve POJO sınıflarını yaratmayacağız.

[codesyntax lang=”java” lines=”no”]

package entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "EMPLOYEE", schema = "CLASSICCARS")
public class Employee implements java.io.Serializable {

    // Fields

    private static final long serialVersionUID = 8874357696210233116L;
    private Integer employeenumber;
    private String lastname;
    private String firstname;
    private String extension;
    private String email;
    private String officecode;
    private Integer reportsto;
    private String jobtitle;

    // Constructors

    /** default constructor */
    public Employee() {
    }

    /** minimal constructor */
    public Employee(Integer employeenumber) {
        this.employeenumber = employeenumber;
    }

    /** full constructor */
    public Employee(Integer employeenumber, String lastname, String firstname,
            String extension, String email, String officecode,
            Integer reportsto, String jobtitle) {
        this.employeenumber = employeenumber;
        this.lastname = lastname;
        this.firstname = firstname;
        this.extension = extension;
        this.email = email;
        this.officecode = officecode;
        this.reportsto = reportsto;
        this.jobtitle = jobtitle;
    }

    // Property accessors
    @Id
    @Column(name = "EMPLOYEENUMBER", unique = true, nullable = false)
    public Integer getEmployeenumber() {
        return this.employeenumber;
    }

    public void setEmployeenumber(Integer employeenumber) {
        this.employeenumber = employeenumber;
    }

    @Column(name = "LASTNAME", length = 50)
    public String getLastname() {
        return this.lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    @Column(name = "FIRSTNAME", length = 50)
    public String getFirstname() {
        return this.firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    @Column(name = "EXTENSION", length = 10)
    public String getExtension() {
        return this.extension;
    }

    public void setExtension(String extension) {
        this.extension = extension;
    }

    @Column(name = "EMAIL", length = 100)
    public String getEmail() {
        return this.email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Column(name = "OFFICECODE", length = 10)
    public String getOfficecode() {
        return this.officecode;
    }

    public void setOfficecode(String officecode) {
        this.officecode = officecode;
    }

    @Column(name = "REPORTSTO")
    public Integer getReportsto() {
        return this.reportsto;
    }

    public void setReportsto(Integer reportsto) {
        this.reportsto = reportsto;
    }

    @Column(name = "JOBTITLE", length = 50)
    public String getJobtitle() {
        return this.jobtitle;
    }

    public void setJobtitle(String jobtitle) {
        this.jobtitle = jobtitle;
    }
}

[/codesyntax]

Entity sınıfını inceleyelim.

@Entity : Sınıfın bir entity sınıfı olduğunu belirtir.

@Table : Sınıfın hangi tabloya karşılık geldiğini ve bu tablonun hangi şemada olduğunu belirtir.

@Id : Tablonun birincil anahtarı (primary key) olduğunu belirtir.

@Column : Değişkenin hangi kolona karşılık geldiğini belirtir.

Ayrıca kullanacağımız entity sınıflarını hibernate.cfg.xml dosyasında tanımlamamız gerekiyor. Çünkü Hibernate’in hangi nesneleri saklaması gerektiğini bilmesi gerekir. Bunu da MyEclipse bizim için otomatik olarak yapıyor.

Hibernate’in tüm özelliklerini kullanmak istiyorsak her entity sınıfında bir tane unique değer olması gerekir. Id isminde veriyorsak getId(), setId() metodlarının erişebilmesi için konfigurasyon dosyasında name=”id” dememiz yeterli olur. Id için set metodunu private yazmamız önerilir. Ayrıca default constructor’ın mutlaka yazılması gerekir. Default constructor private ya da protected olabilir. Sonuçta bu constructor arka planda hibernate tarafından kullanılacaktır.

Şimdi de veri tabanına veri ekleme, silme, güncelleme işlerini yapan test sınıfları yazalım.

[codesyntax lang=”java” lines=”no”]

package dao;

import org.hibernate.Session;
import org.hibernate.Transaction;

import entity.Employee;
import factory.HibernateSessionFactory;

public class CreateData {

    public static void main(String[] args) throws Exception {

        Session sess = HibernateSessionFactory.getSession();
        Transaction tr = sess.beginTransaction();
        Employee emp = new Employee();
        emp.setFirstname("Ricardo");
        emp.setLastname("Quaresma");
        emp.setJobtitle("Futbolcu");
        emp.setEmail("q7@bjk.com");
        sess.save(emp);
        tr.commit();
        System.out.println("Başarıyla eklendi");
    }
}

[/codesyntax]


[codesyntax lang="java" lines="no"]
package dao;

import org.hibernate.Session;
import org.hibernate.Transaction;

import entity.Employee;
import factory.HibernateSessionFactory;

public class UpdateData {
    public static void main(String[] args) throws Exception {
        Session sess = HibernateSessionFactory.getSession();
        Transaction tr = sess.beginTransaction();
        Employee st = (Employee) sess.load(Employee.class, 1);
        st.setFirstname("Simao");
        tr.commit();
        System.out.println("Başarıyla güncellendi");
        sess.close();
    }
}
[/codesyntax]

[codesyntax lang="java" lines="no"]
package dao;

import org.hibernate.Session;
import org.hibernate.Transaction;

import entity.Employee;
import factory.HibernateSessionFactory;

public class DeleteData {
    public static void main(String[] args) throws Exception {
        Session sess = HibernateSessionFactory.getSession();
        Transaction tr = sess.beginTransaction();
        Employee emp = (Employee) sess.load(Employee.class, 1);
        sess.delete(emp);
        System.out.println("Başarıyla silindi");
        tr.commit();
        sess.close();
    }
}
[/codesyntax]

Sınıfları incelerseniz veri tabanı işlemleri için hiç SQL yazmadık. Hazır metotları çağırdık. Ayrıca örnek olsun diye HQL (Hibernate Query Language) kullanarak personelleri listeleyelim. HQL, Hibernate’in kullandığı, SQL’e benzeyen fakat aynı olmayan bir sorgulama dilidir.

[codesyntax lang="java" lines="no"]
package dao;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;

import entity.Employee;
import factory.HibernateSessionFactory;

public class ReadData {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) throws Exception {
        Session sess = HibernateSessionFactory.getSession();
        sess.beginTransaction();
        Query query = sess.createQuery("from Employee");
        List result = query.list();
        Iterator it = result.iterator();
        while (it.hasNext()) {
            Employee emp = (Employee) it.next();
            System.out.print(emp.getFirstname());
            System.out.print("   " + emp.getLastname());
            System.out.print("   " + emp.getJobtitle());
            System.out.println();
        }
    }
}
[/codesyntax]

Bu makalemde Hibernate’in detaylarına inmeden en basit haliyle kullanımına örnek vermek istedim. Asıl kullanımı ise bu kadar basit değildir. SQL’ler çalışma anında dinamik olarak oluşturulduğu için biraz yavaş çalışan Hibernate’in performans artırımı için çeşitli yöntemler vardır.

Hibernate Nedir?

Bu makalemde en çok kullanılan O/RM araçlarından biri olan hibernate hakkında bilgi vermeye çalışacağım.

Hibernate genel anlamda Java sınıflarından veritabanı tablolarına dönüşümü ya da Java veri tiplerinden SQL veri tiplerine dönüşümü gerçekleştirir. Ayrıca veri sorgulama ve veri çekme işlemlerini de kullanıcı için sağlar. Bu özellikleriyle Hibernate uygulamaların geliştirilme aşamasında çok büyük kolaylık ve zamandan kazanç sağlar. Hibernate kullanmadan JDBC ile veri tabanına erişmek mümkündür. Ancak veri tabanındaki tablo sayısı arttığında buna bağlı olarak tablolar arası ilişkiler de artacaktır. Uygulama büyüdükçe bu ilişkiler çok karmaşık bir hal alabilir. Veri tabanı işlemleri için connection açma kapama, ilişkili tablolar için çok karmaşık SQL’ler yazma, aynı fonksiyon içerisinde birden fazla connection almama gibi dikkat etmemiz gereken işler artacaktır. Bu işlemleri yaparken yapacağımız en ufak hata uygulamanın tümünü etkileyecektir. Uygulamamızın mimarisi ne kadar düzgün olursa yapısı da bir o kadar karmaşık olacaktır. Genellikle de en düzgün yapı en karmaşık olanıdır.

Hibernate, hemen hemen yaygın tüm veri tabanı sistemleri ile uyumludur. Bu özelliği ile çok fazla kurum tarafından da kullanılmaktadır.

Hibernate veri kalıcılığını (persistence) sağlamak için veri tabanına karşılık gelen sınıfları ve bu sınıfların konfigurasyon dosyalarını kullanır. Ayrıca hangi veri tabanına nasıl bağlanılacağı bilgilerinin tutulduğu bir XML dosyası da vardır. Sınıflar için kullanılan konfigurasyon dosyalarında hangi sınıfın veri tabanındaki hangi tabloya karşılık geldiği bilgileri ile, kolon özellikleri (primary key, foreign key) tutulur. Sınıflar için kullanılan bu konfigurasyon dosyaları eskiden bir metin dosyasında (XML dosyasında) saklanırken şimdi annotation’lar ile ifade edilmektedir.

SessionFactory : Normal Factory sınıflarının yaptığı işi yapıyor. Hibernate için Hibernate session’ı yaratıyor. Hibernate, her yaratılan thread için tek bir Hibernate Session’ı olmasını bekler. (ThreadLocal sınıfını inceleyiniz) Transactionlar tarafından yönlendirilen veriler için bir çeşit ikincil seviye önbellek tutar.

Session : Session uygulama katmanı ve persistent katman arasındaki iletişimi sağlar. Session nesnelere bir identifier ile erişimi, nesneler arası gezinmeyi saglar. Session, JDBC bağlantısını transaction’lar için bir factory sınıfı olarak görür.

Persistent Nesneler : Bu nesneler sıradan JavaBean’ler olabilirler, ama en önemli özellikleri halihazırda tek bir Session nesnesiyle ilişkili olmalarıdır. İçlerinde iş yapan metodlar da olabilir. Session kapanır kapanmaz, bu nesnelerin Session ile ilişkileri sona erer ve uygulama katmanından yönlendirilmeye, kullanılmaya hazır duruma geçerler.

Örnek JPA Uygulaması

Şimdi JPA kullanarak veri tabanına basit bir insert işlemi gerçekleştiren uygulama yazalım. Bu uygulamayı MyEclipse ortamında Derby veri tabanı kullanarak yazacağız. Siz kendi kullandığınız bir IDE’de farklı bir veri tabanı kullanarak da yapabilirsiniz. JPA’ya direk destek vermesi ve içerisinde örnek tabloların olması sebebiyle ben MyEclipse kullanacağım.

Önce Package Explorer penceresinde New -> Java Project diyerek bir proje yaratıyoruz.

Daha sonra projemize Sun standartlarına bağlı kalarak bir isim veriyoruz, diğer ayarları olduğu gibi bırakarak Finish butonuna tıklıyoruz. Ben isim olarak JPAOrnek verdim.

Projemiz sınıflarımızın bulunacağı src ismindeki bir dizin ve Java’nın standart kütüphaneleri ile yaratıldı. Şimdi projemizde JPA kullanacağımızı belirteceğiz. Bunun için proje üzerinde sağ klik, MyEclipse menüsünden Add JPA Capabilities…  seçeneğine tıklıyoruz.

Açılan sayfada bize JPA’nın implementasyonları olan teknolojilerden hangisini kullanmak istediğimizi soruyor. Biz bu uygulama için OpenJPA seçelim ve Next diyelim. Bütün teknolojilerin kullanımı birbirine çok benzer. Siz isterseniz Hibernate ya da Toplink teknolojilerinden birini de seçebilirsiniz.

Açılan sayfada bağlanılacak olan veri tabanı hakkında driver bilgisi ile schema bilgisini gireceğiz. Ben MyEclipse içerisinde hazır gelen Derby’yi kullanacağım için onun driver’ını seçiyorum. SQL Server, Oracle ya da başka bir veri tabanına bağlanmak istiyorsanız yan taraftaki Create new driver linkinden yeni bir driver tanımlayabilirsiniz.

Bu sayfada ayrıca Persistence unit name bilgisini girmemiz gerekiyor. Standart olarak proje ismimin sonuna PU eklenmiş ama istersek değiştirebiliriz. Bu isim daha sonra Entity Manager yaratırken kullanılacağı için önemlidir.

Driver bilgisinin hemen altında Copy DB driver jar(s) ile başlayan bir seçenek var. Bunu işaretlediğimiz taktirde projemizin veri tabanına bağlanabilmek için ihtiyaç duyduğu client driver otomatik olarak projeye eklenecektir.

Finish butonun tıkladığımızda OpenJPA kütüphaneleri, clientDriver.jar projeye eklenmiş ve META-INF adlı özel dizin içerisinde persistence.xml adında bir dosya oluşturulmuştur.

Bu dosya içerisinde projenin bağlanağı veri tabanı hakkında driver, connection-url gibi bilgiler yer almaktadır. Daha sonra veri tabanına karşılık gelen entity sınıflarımızı da yine bu dosya içerisine tanımlayacağız. Entity sınıflarımızı elle yazabildiğimiz gibi otomatik olarak yaratmak da mümkündür. Bunun için MyEclipse Database Explorer perspektifine geçerek, entity sınıfını yaratacağımız tablonun üzerinde sağ klik JPA Reverse Engineering… seçeneğine tıklıyoruz.

Açılan pencerede entity sınıfımızı nereye yaratmak istediğimizi belirtiyoruz. Ben daha önceden yaratmış olduğum entity paketi altına yaratılsın diyorum. Yaratılırken de persistence.xml dosyası güncellensin seçeneğini işaretliyorum. Bu sayede persistence.xml dosyasına entity sınıfımız otomatik olarak tanımlanmış oluyor.

Finish dediğimizde entity paketi altında seçtiğimiz tablo ile aynı isimde bir sınıf yaratılarak bu sınıfın referansı persistence.xml dosyasına yazılmış oluyor.

Örnek olarak kullandığımız Customer tablosunun tüm kolonları için Customer sınıfında birer değişken yaratıldı.

[codesyntax lang=”java” lines=”no”]

package entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Customer entity. @author MyEclipse Persistence Tools
 */
@Entity
@Table(name = "CUSTOMER", schema = "CLASSICCARS")
public class Customer implements java.io.Serializable {

    // Fields

    private static final long serialVersionUID = -4279273036023102468L;
    private Integer customernumber;
    private String customername;
    private String contactlastname;
    private String contactfirstname;
    private String phone;
    private String addressline1;
    private String addressline2;
    private String city;
    private String state;
    private String postalcode;
    private String country;
    private Integer salesrepemployeenumber;
    private Double creditlimit;

    // Constructors

    /** default constructor */
    public Customer() {
    }

    /** minimal constructor */
    public Customer(Integer customernumber) {
        this.customernumber = customernumber;
    }

    /** full constructor */
    public Customer(Integer customernumber, String customername,
            String contactlastname, String contactfirstname, String phone,
            String addressline1, String addressline2, String city,
            String state, String postalcode, String country,
            Integer salesrepemployeenumber, Double creditlimit) {
        this.customernumber = customernumber;
        this.customername = customername;
        this.contactlastname = contactlastname;
        this.contactfirstname = contactfirstname;
        this.phone = phone;
        this.addressline1 = addressline1;
        this.addressline2 = addressline2;
        this.city = city;
        this.state = state;
        this.postalcode = postalcode;
        this.country = country;
        this.salesrepemployeenumber = salesrepemployeenumber;
        this.creditlimit = creditlimit;
    }

    // Property accessors
    @Id
    @Column(name = "CUSTOMERNUMBER", unique = true, nullable = false)
    public Integer getCustomernumber() {
        return this.customernumber;
    }

    public void setCustomernumber(Integer customernumber) {
        this.customernumber = customernumber;
    }

    @Column(name = "CUSTOMERNAME", length = 50)
    public String getCustomername() {
        return this.customername;
    }

    public void setCustomername(String customername) {
        this.customername = customername;
    }

    @Column(name = "CONTACTLASTNAME", length = 50)
    public String getContactlastname() {
        return this.contactlastname;
    }

    public void setContactlastname(String contactlastname) {
        this.contactlastname = contactlastname;
    }

    @Column(name = "CONTACTFIRSTNAME", length = 50)
    public String getContactfirstname() {
        return this.contactfirstname;
    }

    public void setContactfirstname(String contactfirstname) {
        this.contactfirstname = contactfirstname;
    }

    @Column(name = "PHONE", length = 50)
    public String getPhone() {
        return this.phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Column(name = "ADDRESSLINE1", length = 50)
    public String getAddressline1() {
        return this.addressline1;
    }

    public void setAddressline1(String addressline1) {
        this.addressline1 = addressline1;
    }

    @Column(name = "ADDRESSLINE2", length = 50)
    public String getAddressline2() {
        return this.addressline2;
    }

    public void setAddressline2(String addressline2) {
        this.addressline2 = addressline2;
    }

    @Column(name = "CITY", length = 50)
    public String getCity() {
        return this.city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Column(name = "STATE", length = 50)
    public String getState() {
        return this.state;
    }

    public void setState(String state) {
        this.state = state;
    }

    @Column(name = "POSTALCODE", length = 15)
    public String getPostalcode() {
        return this.postalcode;
    }

    public void setPostalcode(String postalcode) {
        this.postalcode = postalcode;
    }

    @Column(name = "COUNTRY", length = 50)
    public String getCountry() {
        return this.country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    @Column(name = "SALESREPEMPLOYEENUMBER")
    public Integer getSalesrepemployeenumber() {
        return this.salesrepemployeenumber;
    }

    public void setSalesrepemployeenumber(Integer salesrepemployeenumber) {
        this.salesrepemployeenumber = salesrepemployeenumber;
    }

    @Column(name = "CREDITLIMIT", precision = 52, scale = 0)
    public Double getCreditlimit() {
        return this.creditlimit;
    }

    public void setCreditlimit(Double creditlimit) {
        this.creditlimit = creditlimit;
    }
}

[/codesyntax]

Son olarak da veri tabanına insert işlemini yapacak olan bir test sınıfı yazalım.

[codesyntax lang="java" lines="no"]
package test;

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

import entity.Customer;

public class Test {

    public static void main(String[] args) {
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("JPAOrnekPU");
        EntityManager em = entityManagerFactory.createEntityManager();
        EntityTransaction userTransaction = em.getTransaction();

        userTransaction.begin();
        Customer customer = new Customer();
        customer.setAddressline1("Yenimahalle");
        customer.setAddressline2("Çayyolu");
        customer.setCity("Ankara");
        customer.setContactfirstname("Tuba");
        customer.setContactlastname("Pehlivan");
        customer.setCountry("Türkiye");
        customer.setCreditlimit(9700.00);
        customer.setCustomername("Erkin");
        customer.setCustomernumber(111111);
        customer.setPhone("312899423");
        customer.setPostalcode("06810");
        customer.setSalesrepemployeenumber(12);
        customer.setState("İç Anadolu");
        em.persist(customer);
        userTransaction.commit();
        em.close();
        entityManagerFactory.close();
    }
}
[/codesyntax]

EntityManagerFactory yaratırken kullandığımız createEntityManagerFactory() metoduna parametre olarak persistence.xml dosyasında tanımladığımız persistence unit name değerini veriyoruz. Daha sonra factory üzerinden EntityManager instance’ı oluşturarak transaction alıyoruz. Transaction’ı başlatıp entity sınıfımızın değişkenlerini set ediyoruz. Farkettiğiniz gibi Customer tablosu ile hiç uğraşmadık. Sadece entity sınıfımızın değişkenlerini set ettik. Arka tarafta JPA, JDBC alt yapısını kullanarak veri tabanına bağlandı ve yeni kayıt ekledi.

Veri tabanını kontrol edersek yeni kaydın Customer tablosuna eklendiğini görürüz.

Object Relational Mapping

Java’da Nesne İlişkisel Eşleme (Object Relational Mapping)

Adından da anlaşılacağı gibi nesne ilişkisel eşleme yani ORM, veri tabanı ile ilgili işlemleri kod tarafında nesneler (sınıflar) ile yönetebilmemizi sağlayan programlama tekniğidir. ORM ya da O/RM ya da O/R Mapping, Object Relational Mapping’in kısaltmasıdır. Bu teknik sayesinde programcı veri tabanı ile ilgili işlemler yaparken sorgu çekmekle yani SQL yazmakla uğraşmaz. Onun yerine sınıflar üzerinden işlemlerini gerçekleştirir.

Diğer dillerde olduğu gibi Java dilinde de birçok ORM kütüphanesi vardır. En çok kullanılanlardan bazıları şunlardır.

–          JPA

–          Hibernate

–          OpenJPA

–          Toplink

–          EclipseLink

–          IBatis

–          Apache Cayenne

Veri tabanlarında yer alan tablo, kolon, tablolar arası ilişki (association) gibi kavramların yazılım tarafında birebir karşılıkları yoktur. Bu kavramların karşılıkları olarak örneğin tablo için sınıf, kolon için değişken gibi bileşenler kullanılır. Fakat sadece bu kadarı büyük projeler için yeterli olmayacaktır. Tablolar arası ilişkiler arttıkça ve karmaşıklaşmaya başladıkça yazılımcının veri tabanından yapacağı sorgular da işin içinden çıkılamaz hale gelecektir. JDBC ile veri tabanına erişmek çok hızlı olmasına rağmen bahsettiğim sebeplerden ötürü büyük çaptaki projelerde ORM araçları sıklıkla kullanılır.

ORM kullanan bir programcının SQL ya da JDBC bilmesine gerek kalmaz. Kodunu geliştirirken daha kısa zamanda daha az kod yazarak veri tabanına bağlanabilir. Fakat bunun yanında SQL’ler çalışma anında dinamik olarak üretildiği için yavaş çalışır.

HQL – Hibernate Query Language

Hibernate’te kullanılan sorgulama dili olan HQL, genel anlamda SQL’e benzer. SQL’e benzer ancak aslında temelde aralarında çok büyük farklar vardır. SQL (Structured Query Language) veri tabanı nesneleri ile birlikte çalışırken, HQL Java sınıflarıyla birlikte çalışır.

HQL kullanırken yazdığımız sorgularda küçük büyük harf duyarlı yazmamıza gerek yoktur. Yalnız HQL sınıflarla birlikte çalıştığı için sınıf isimlerini tanımlandıkları şekilde yazmamız gerekir. Örneğin Futbolcu adında bir sınıfımız varsa bu sınıfla ilgili sorgu yazarken diğer kullandığımız HQL terimlerinin nasıl yazıldığı önemli değil ancak sınıfın isminin Futbolcu olarak küçük büyük harfe dikkat ederek yazmamız gerekir.

Şimdi Hibernate’te en çok kullanılan HQL terimlerine bir göz atalım :

Select : Çok fazla kullanılmasa da nesnelerin hangi özelliklerinin döndürüleceğinin belirtildiği kısımdır. SQL’de tabloların kolonları gibi düşünebiliriz. Birçok farklı sınıftan birçok değişik özellik veri tabanından istenebilir.

Select cümleciğinin en büyük özelliği kendisinden sonra new operatörü ile yeni bir nesne instance’ı yaratılabilmesidir. Örneğin ;

Select new Futbolcu(Calisan adi) from Takim … gibi

From : SQL’deki mantıkla çalışır. Veri tabanında from cümleciğinden sonra yazılan nesneye karşılık gelen tablo ile ilgilenir.

Join : SQL’deki tüm join tipleri de HQL’de aynen kullanılabilir.

–       inner join

–       left outer join

–       right outer join

HQL’de join işlemleri join terimi yazılarak ve yazılmadan iki farklı şekilde yapılabilir.

Where : Nesneler için kısıtlamalar getirmemizi sağlayan terimdir. Where teriminden sonra yazacağımız değişkenin değerini setlerken genellikle “= :” ifadesinden sonra isim verilir. Değişken değeri daha sonradan atanır.

Query hql = session.createQuery(“From Futbolcu where adi = : futbolcuAdi”);

Hql.setParameter(“futbolcuAdi”, “Quaresma”);

Group by : Sorgu sonucu dönen nesnelerin gruplandırılmasını sağlayan terimdir.

Order by : Sorgu sonucu dönen nesnelerin sıralanmasını sağlayan terimdir. Order by’dan sonra yazdığımız özelliğe göre sıralama gerçekleşecektir.

Gördüğünüz gibi yapı olarak SQL dili ile benzer özellikler göstermektedir. Zaten HQL bu sayede öğrenmesi ve kullanması çok kolay bir dildir. Unutulmaması gereken şey Hibernate’in nesnelerle düzgün bir şekilde çalışabilmesi için sınıfların JavaBean nesneleri olarak yaratılması gerektiğidir.