Herşey ilk adımlarla başlar...

Thursday, September 24, 2009

Adım Adım Hibernate - Hibernate ilk uygulama

9/24/2009 Posted by Nurettin Onur YAKIT , , , , , , 8 comments


Hibernate nedir artık biliyoruz.. Veritabanı işlemlerinde bize yardımcı olan, obje kavramından uzaklaşmadan işimize devam etmemizi sağlayan bir yapı.

Artık;

INSERT INTO mytable(name, surname, country) VALUES ("Nurettin" , "YAKIT", "Türkiye")

Yerine,

session.save(person);
Kullanıyoruz.

Peki Hibernate bunu nasıl yapıyor?

Hibernate gibi ORM (Object - Relational Mapping) araçları bir nesnenin veri tabanında hangi tabloya karşılık geldiğini işaretler. Bu işaretleme işlemine mapping denir. Mapping'in nasıl olacağına biz karar veririz.
Hibernate veritabanına kayıt işlemi için POJO'lardan yararlanır, bir POJO (Plain Old Java Object) sadece attribute ve getter/setter 'lerden oluşan basit bir java nesnesidir.
Hibernate'in bu POJO'yu veritabanında hangi tablo'ya saklayacağını, nasıl saklayacağını mapping dosyasında yani pojoIsmi.hbm.xml 'inde belirtiriz. Bundan sonra bize sadece session.save() metodunu çağırmak kalır.

Bir Hibernate projesinde bulunması gereken temel dosyalar şöyledir :

-hibernate.cfg.xml
-Person.hbm.xml (Pojomuz Person.java)
-jar'lar

Mapping dosyası Person.hbm.xml , POJO'muz Person.java'nın bulunduğu dizinde olmalıdır. Ayar dosyamız hibernate.cfg.xml ise ide tarafından tanınabileceği, projenin bir üst dizininde bulunmalıdır.


Uygulama Vakti

Şimdi daha iyi anlamak için basit bir uygulama yapalım. Sadece bir tane person nesnesi yaratalım ve bu nesneyi veritabanımıza kaydedelim.

Hibernate kullanabilmek için Hibernate Core paketini indirmeniz yeterli, benim şimdi indirdiğim paket 3.3.2.GA ama siz bu yazıyı okurken daha yeni bir sürüm çıkmışsa onu indirmenizi öneririm.

Veritabanı olarak istediğiniz veritabanını kullanabilirsiniz. Benim size tavsiyem pür java olduğundan ve çok az yer kapladığından böyle basit uygulamalarda kullandığım HsqlDb. Ben bu yazıyı yazarken son stabil sürüm 1.8.1.1 idi 1.9.0 'da geliştirilmekte ama şu an için stabil olarak değerlendirmiyorlar bu nedenle son stabil sürümü indirmeniz daha iyi olacaktır.

İndirdiğiniz dosyayı herhangi bir yere açabilirsiniz. Ama benim tavsiyem root'a yakın bir yere Development adında bir klasör oluşturmanız ve oraya açmanız .

Linux --> /home/wind/Development/hsqldb
Windows --> c://Development/hsqldb

Hsqldb kullanabilmek için gerekli olan jar dosyamız ../Development/hsqldb/lib altındaki hsqldb.jar o yüzden orada olduğundan emin olun.

Artık Eclipse'mizi açabiliriz. HibernateSample adında bir proje oluşturuyoruz. Projemizde bu jar dosyasını kullanacağımız için build path'den ekliyoruz. Ama size tavsiyem hem taşınabilirliği hem de yönetebilirliği arttırmak için kullanacağınız jar'ları projenizin içinde oluşturduğunuz bir folder'a koymanız. Mesela mylib adında bir folder oluşturun. Bunun için projemizin üzerindeyken sağ tıklayarak new sekmesinden folder seçelim.




Daha sonra hsqldb.jar dosyasını bu folder'in içine koyalım, hsqldb.jar dosyasını kopyalayıp mylib'e sağ tıklayıp yapıştır demek yeterli. Artık projeye sağ tıklayıp Build Path->Configure Build Path menüsündeki Libraries sekmesinden Add Jars ile jar dosyamızı ekleyebiliriz.





İşte bu kadar.. Bundan sonra HsqlDb veri tabanını istediğimiz gibi kullanabiliriz.

Şimdi gelelim hibernate ile ilgili kısımlara.. Gereken jar dosyaları indirdiğimiz Hibernate Core paketinde bulunuyor. HsqlDb'de yaptığımız gibi gereken jar dosyalarını mylib klasörüne kopyalıyoruz ve Build Path'imize ekliyoruz. Bunlar :

-antlr-2.7.6.jar
-commons-collections-3.1.jar
-dom4j-1.6.1.jar
-hibernate3.jar
-javassist-3.9.0.GA.jar
-jta-1.1.jar
-slf4-api-1.5.8.jar

versiyon numaraları indirdiğiniz Hibernate sürümüne göre değişiklik gösterebilir. Ama büyük ihtimalle indirdiğiniz sürümdeki lib/required altındaki jar dosyaları (ve tabi ki hibernate'in kendi jar'ı) yeterli olacaktır.

Şimdi hibernate için bir adet configuration xml'i oluşturalım. Projemize sağ tıklayarak New->Other menüsünden XML i seçiyoruz. İsim olarak hibernate.cfg.xml veriyoruz. Ve bu xml dosyasına hibernate'in hangi dili konuşacağı (dialect), veritabanının nerede olacağı, hangi kullanıcı adı ile bağlanacağı, hangi şifreyi kullanacağını yazıyoruz. Opsiyonel olarak oluşturduğu sql sorgularını göstermesini de isteyebiliriz.


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<property name="hibernate.dialect"> org.hibernate.dialect.HSQLDialect </property>
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="hibernate.connection.url">jdbc:hsqldb:file:/media/LagerHaus/ProjectsDBS/blogDb</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.show_sql">true</property>



</session-factory>

</hibernate-configuration>





Şimdi person sınıfımızı oluşturalım, projeye sağ tıklıyor ve New -> Class seçiyoruz.




Person sınıfımızda id, name, surname bilgilerini tutuyoruz. Ve hibernate'in bunlara erişebilmesi için gerekli getter ve setter metodlarını da oluşturuyoruz. Bunun için id, name, surname attribute'lerini oluşturduktan sonra sınıfımıza sağ tıklayarak Source->Generate Getters and Setters menüsünde oluşturacağımız metodları seçerek otomatik oluşturulmasını sağlayabiliriz.


Oluşan pojomuz kullanıma hazır ;

package com.pojo;

public class Person {

int id;
String name;
String surname;

public int getId() {
return id;
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getSurname() {
return surname;
}

public void setSurname(String surname) {
this.surname = surname;
}

}





Şimdi bu sınıfın mapping dosyasını oluşturalım. Bunun için Person.java 'nın bulunduğu yere Person.hbm.xml adında bir XML dosyası oluşturalım.



<hibernate-mapping>

 <class name="com.pojo.Person" table="person">

  <id column="id" name="id">
   <generator class="increment"></generator>
  </id>

  <property column="name" length="20" name="name" type="string"></property>
  <property column="surname" length="20" name="surname" type="string"></property>


 </class>

</hibernate-mapping>  

Şimdi oluşturduğumuz bu mapping dosyasını hibernate'ye tanıtalım, bunun için hibernate.cfg.xml dosyasına şu satırı ekliyoruz;
<mapping resource="com/pojo/Person.hbm.xml"> </mapping>
Bir de gerekli tabloların veritabanında bulunmadığı ve bu tabloları hibernate'in kendisinin oluşturmasını istediğim için şu satırı da ekliyorum;

<property name="hibernate.hbm2ddl.auto">update</property>

Artık gerekli ayarları da yaptık, bundan sonra nesnemizi istediğimiz gibi kontrol edip istediğimiz zaman veritabanına kaydedebiliriz..



package com.startpoint;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import com.pojo.Person;

public class Test {

 public static void main(String[] args) {

  // Bir tane session tanımlıyoruz.
  Session session = null;

  // hibernate.cfg.xml dosyasındaki ayarlara ait bir session factory
  // yaratıyoruz
  SessionFactory sessionFactory = new Configuration().configure()
    .buildSessionFactory();

  // Bu session Factory'den bir session açıyoruz.
  session = sessionFactory.openSession();

  // Bir transaction açıyoruz
  Transaction transaction = session.getTransaction();

  try {

   // Yapılacak işlemleri yapıyoruz
   Person person = new Person();
   person.setName("Nurettin");
   person.setSurname("YAKIT");

   transaction.begin(); // Transaction'umuzu başlatıyor
   session.save(person); // person objemizi save ediyor
   transaction.commit(); // ve bu transaction'u veri tabanına
         // gönderiyoruz.

  } catch (Exception e) {
   e.printStackTrace();
  }
  
  finally{
   session.close(); //veritabanı işlemimiz başarılı olsa da olmasa da session'umuzu kapatıyoruz.
  }
  

 }

} 
 

Uygulamamızı çalıştırdığınızda SLF4J hatası alabilirsiniz. Hibernate'in bu sürümünde ilgili jar dosyasında bir sıkıntı olabiliyor. Bu durumda http://www.slf4j.org/codes.html adresine bakmanızda fayda var. Buradan indirdiğiniz slf4j-1.5.8.zip dosyasının içindeki slf4j-simple-1.5.8 jar dosyasını yine mylib içine kopyalayarak Build Path'e eklememiz yeterli.

Veritabanı olarak hsqldb kullandığınızda kaydetme esnasında sıkıntı yaşarsanız. Veritabanımızın bulunduğu klasördeki veritabanıismi.script dosyasında bulunan SET WRITE_DELAY 'i 0 yapın.

Düşündüğümden daha uzun oldu sanırım.. Umarım faydalı olmuştur.. Herhangi bir yerde takılırsanız, bir sorun ile karşılaşırsanız veya aklınıza takılan başka birşey olursa hiç çekinmeden sorun.. En kısa zamanda yanıtlamaya çalışırım.



8 comments:

Anonymous said...

"Veritabanı olarak hsqldb kullandığınızda kaydetme esnasında sıkıntı yaşarsanız. Veritabanımızın bulunduğu klasördeki veritabanıismi.script dosyasında bulunan SET WRITE_DELAY 'i 0 yapın."

Buraya kadar anlaşılır durumda yalnız vt nerede kaydediliyor biraz daha açabilirseniz sevinirim. Vt bulunduğu klasör neresidir?

Nurettin Onur YAKIT said...

Merhabalar,

Aslında tam olarak nerede sıkıntın olduğunu anlayamadım..

Yine şöyle bir şeyler yapabiliriz :

vt derken veri tabanından bahsediyor olmalısın. Veri tabanımız benim verdiğim örnekte şu url de bulunuyor:

jdbc:hsqldb:file:/media/LagerHaus/ProjectsDBS/blogDb

yani /media/LagerHaus/.. sen buraya eğer windows kullanıyorsan c:/.../.. gibi birşeyler yazmış olmalısın. Yani senin veri tabanının bulunduğu yer bundan sonra orasıdır.

Daha önce access kullandıysan orada veritabanını bir dosya olarak görebilirsin. Ama Oracle veya Hsqldb gibi veritabanları dosya olarak görünmez. Sadece bulunduğu path (klasörü) bilinir.

Umarım bu soruna cevap olur. Eğer anlamadığı bir yer varsa belirtirsen sevinirim. Bir de eğer yorum yaparken ismini de yazarsan güzel olur.

Mahmut Akbolat said...

Merhaba, derli toplu çalışmanız için teşekkür ederim.

slf4j den gelen logları iptal etmemizin bir yolu var mı?


Aşağıdaki gibi uzayıp giden log mesajları consol ekranına geliyor kendi loglarım bunların arasında kaybolup gidiyor. Yardımcı olursanız şimdiden teşekkür ederim

31 [main] INFO org.hibernate.cfg.Environment - Hibernate 3.3.2.GA
31 [main] INFO org.hibernate.cfg.Environment - hibernate.properties not found
31 [main] INFO org.hibernate.cfg.Environment - Bytecode provider name : javassist
47 [main] INFO org.hibernate.cfg.Environment - using JDK 1.4 java.sql.Timestamp handling

alpant said...

Merhaba,

hibernate kullanarak bir nesneyi vt na kaydederken sürekli hata alıyorum. daha doğrusu işlem gerçekleşti diyor ancak vt na bakıyorum kayıt eklenmemiş. nesnenin çok fazla özelliğini set ediyorum acaba bununla bi ilgisi olabilir mi?

Nurettin Onur YAKIT said...

Merhabalar Alpant,

Nesnenin ne kadar özelliğini set ettiğinle alakalı olacağını sanmıyorum.

Büyük ihtimalle bir konfigürasyon hatası olmuştur. Verdiğin path'leri bir kontrol et.

Anonymous said...

Yazı için teşekkürler.
Commentlerle satır satır açıklamanız çok iyi olmuş. PL/SQL derslerinizinde devamını bekliyorum.

Yalnız bir şey gözüme çarptı Transcation olayına değinilmemiş.

Session nesnesinin tam olarak ne iş yaptığını anlayamadım. Neden Session başlatıp commit ettikten sonra sonlandırmamız gerekiyor ? Hibernate bunu kendisi yapamıyor mu ? Bağlantı açıp kapatmak gibi bir şey mi ? Arka planda ne yapıyor ?

Teşekkürler.

Seval U. said...

Yıl 2013 ve ben bu yazıyı okudum:) Gerçekten hala faydalı ve güncelliğini koruyan bir yazı olmuş. Bu kadar aydınlatıcı yazılar yazdığınız için teşekkürler.

Nurettin Onur YAKIT said...

Merhabalar Seval,

Faydalı olmasına sevindim :)

Teşekkür ederim.