RESTful Web Servisleri – Hibernate

Şimdiye kadar mimarizimi kurmuş, veritabanını hazırlamış ve veritabanına ait JPA modellerini oluşturduk. Şimdi ise bu sınıfları kullanarak, veritabanı işlemlerini nasıl yapacağımıza bakacağız.

Içindekiler

  1. Hazırlık
    1. Projenin Yaratılması
    2. Veritabanının Yaratılması
  2. JPA Modellerinin Oluşturulması
  3. Hibernate DAO Sınıflarının Yazılması
  4. Web Servisin Yazılması
  5. GAE Üzerine Web Servisin Yüklenmesi
  6. Web Servis İçin İstemcilerin Yazılması

3. Hibernate ile DAO Sınıflarının Yazılması

DAO sınıflarını hibernate kullanarak yazacağız. Fakat DAO sınıflarını yazmak için hibernate içerisinde çeşitli yapılan bulunmaktadır. Biz bu yapılar içerisinden Criteria API olarak adlandırılan yapıyı kullanacağız. Eğer başka yapılarıda merak ediyorsanız Example API ve HQL yapılarını inceleyebilirsiniz.

Eğer daha önce JPQL (Java Persistance Query Language) ile kod geliştirdiyseniz, Criteria API yapısını kullanmakta hiç zorlanmayacaksınız. Kısaca Criteria API, kullandığınız model yapıları üzeirnden yapacağınız kısıtlamalarla veri çekmenize izin vermektedir.

Genel olarak çalıştığım şirketlerde de Criteria API kullanıyorum. Eğer çalıştığım şirket farklı bir API kullanıyorsa onlarıda Criteria API’ına yönlendiriyorum. Çünkü Criteria API sizi olabildiğince SQL katmanından soyutluyor. Hiç bir şekilde SQL benzeri bir yapıyla uğraşmıyorsunuz. Temelde JPQL ile yaptığı aynı şey olsada, JPQL gibi SQL benzeri bir yapısı olmadığından benim öncelikli tercihim Criteria API oluyor.

3.1 Hazırlık

Öncelikle şunu söylemeliyim Criteria API, Hibernate Session sınıfı üzerinden çalışıyor. Bunun için önceki bölümde oluşturduğumuz hibernate.cfg.xml dosyasını kullanarak kendimize bir SessionFactory sınıfı yaratacağız. Bu sınıf Singleton Pattern ile oluşturulacak. Session nesnelerimizi her bir “Thread” için otomatik olarak oluşturacağız. Ayrıca “Transaction”‘larımız, READ_COMMTED çalışacak. Eğer bu gibi konularda zorluk yaşıyorsanız, size tavsiyem şu hibernate yazısını okuyun ve devam etmeden önce Criteria API kullanarak bir kaç egzersiz yapın.

Eğer genel olarak Criteria API kullandıysanız, bazı işlemlerin tüm DAO’lar tarafından paylaşıldığını göreceksiniz. Bende genel olarak Criteria API’ını kullandığım için, kendime bir kütüphane hazırladım. Kütüphaneyi şu git deposu üzerinden inceleyebilirsiniz. Çekinmeden “fork” edebilirsiniz.

Bende projede ilerlerken, çalıştığım şirketlerde olduğu gibi, bu git deposundaki kodların üzerinden ilerleyeceğim. Bu depoyu kullanmak için modellerinizin belirli sınıfları içermesi gerekmektedir. Ayrıca DAO sınıfınızında belirli sınıflardan türemiş olması gerekmektedir. Kullanılan sınıflarda commons-lang3 bağımlılığı bulunmaktadır. Bunu rest-db projesinin pom.xml’ine aşağıdaki bağımlığı ekleyerek yapabilirsiniz.

pom.xml
 

Ayrıca hibernate.cfg.xml dosyasına da gerekli satırları eklemeliyiz. Bu sayede hem Car ve User sınıflarının Entity olduğunu belirtmiş oluyoruz hemde az önce bahsettiğim Transaction ve Session ayarlarını yapmış oluyoruz. Son haliyle hibernate.cfg.xml dosyam aşağıdaki gibidir.

hibernate.cfg.xml

3.2 Modellerin Hazırlanması

Şimdi bağımlılıklarımızıda eklediğimize göre oluşturduğumuz Car ve User modellerini kendi kullanacağımız DAO sınıfıları için uygun hale getirebiliriz. Öncelikle modellerimiz için bir Interface yapalım. Bu sınıfı yaratırken tüm modellerimizi ve hatta bundan sonra eklenebilecek modelleride kapsayacak şekilde olmasına özen gösterelim. En basitinden tüm modellerimizin birer id si olacak. Sonra mesela tüm sınıflarımızın yeni mi yaratılmış yoksa veritabanından çekilmiş olduğunu anlayabileceğimiz metodlara ihtiyacımız olacak. Bunları düşündüğümüzde karşımıza aşağıdaki gibi bir interface çıkıyor.

IEntity.java
 

Şimdi ise bu interafce içinde tanımlanmış fakat bütün modeller için aynı olacak methodların yazımına geçelim. Örneğin yeni olup olmadığnı anlayacağımız method tüm modeller için aynı olacaktır. Fakat her modelin id bilgisi farklı olacaktır. Bundan dolayı id bilgisini esas modele bırakıp diğer methodların yazımına geçiyoruz.

AbstractEntity.java

Bu sınıfta commons-lang3 kütüphanesine neden bağımlılığımızın olduğunu ufak ufak anlıyorsunuzdur ama ben yinede belirtmek istiyorum. Kullandığımız Builder sınıfları bizim işimizi çok kolaylaştırıyor. Hemen hemen her projemde StringUtils, EqualsBuilder, CompareToBuilder, Validator sınıflarını kullanıyorum. Çünkü kullanmadığım zaman bu methodları ben yazıyorum ve hazır yazılmışı varken bir daha yazmak bana çok saçma geliyor. Sonuçta DRY(Do not Repeat Yourself) önemli bir ilke.

Şimdi modellerimize yani Car ve User sınıfını AbstractEntity sınıfından türetiyoruz. Yani tüm implements ve extends yapılarını silip sadece extends Abstract Entity eklemeniz yeterli. Sonuca sizde şaşıracaksınız ama başka hiç bir değişiklik yapmanıza gerek kalmayacak.

3.3 SessionFactory Sınıfının Yaratılması

Modellerimizi hazırladığımıza göre şimdi sıra DAO sınıflarını yazmaya geldi. Fakat DAO sınıflarımız Hibernate Session sınıfı isteyeceğinden öncelikle Hibernate Session sınıflarını üreten SessionFactory sınıfını oluşturmamız gerekiyor. Fakat SessionFactory sınıfı oluşturması pahalı bir sınıf olduğundan bu sınıfı Singleton Pattern ile oluşturacağız.

Kısace Singleton Pattern, bir sınıfın belirlediğiniz alan içerisinde bir kere oluşturulmasını garantileyen bir sınıf kalıbıdır. Bizim istediğimiz alan tüm uygulama olduğundan bu doğrultuda çalışacak bir sınıf yaratacağız. Bu sınıf ise oluşurken bir tane Hibernate SessionFactory sınıfı yaratacak.

HibernateUtil.java

3.4 DAO Sınıflarının Yaratılması

DAO sınıflarımızı yaratırken, modellerimizi hazırlarken kullandığımız mantığı kullanacağız. Öncelikle tüm DAO sınıflarında ortak olan, metodları belirleyeceğiz. Bu metodları bir interface sınıfına çıkartacağız. Ardından yine tüm DAO sınıflarında ortak olarak kullanılacak metodları uygulayacağız. Ardından her bir model için DAO sınıflarını oluşturacağız. Yaratacağımız interface’te en basitinden CRUD operasyonları olacak, bunun haricinde JPA için gerekebilecek refresh, merge tarzı yapılarımızda olacak. Ayrıca ID ile sorgu çekme ve SQL ile sorgu çekme gibi methodlarımızda olacak.

IBaseDAO.java

Şimdi ise bu sınıfı hibernate için uyarlayan soyut sınnıfımızı yazalım.

BaseHibernateDAO.java
Burdan sonra ise UserDAO ve CarDAO sınıflarını oluşturalım. Bu sınıfların yapacağı tek şey BaseHibernateDAO sınıfından türemek ve IUserDAO ve ICarDAO sınıfılarını implemente etmek. IUserDAO ve ICarDAO sınıfları ise IBaseDAO sınıfından türemiş interface sınıflarıdır.

IUserDAO.java

UserDAO.java
 

ICarDAO.java

CarDAO.java

3.5 Sonuç

Şu anda en temel veritabanı işlemlerini yapabilecek şekilde sınıflarınızı hazırlamış bulunuyorsunuz. İsterseniz kendiniz testlerinizi yapabilir ya da daha ileri giderek gerçek testler yazabilirisniz. İlk başta modellerinizin DAO’larının boş olması sizi rahatsız edebilir. Fakat BaseHibernateDAO sayesinde çoğu işlemi kolaylıkla yapabilirsiniz. Hatta yazdığımız metodlar sayesinde yeni sorgularınızıda kolaylıkla ekleyebilirsiniz.

Biz ise yeni sorgularımızı web servisini yazmaya başladığımızda ekleyeceğiz. Şimdilik bu projeyi bitirmiş gibi gözüksekte ilerde geri dönüp önce interface sınıflarımızıa gereken metodları ekleyeceğiz. Ardındanda gerçek DAO sınıflarımızda bu methodları gerçekleyebileceğiz.

Bu mimari sizi biraz korkutmuş olabilir ya da gereğinden fazla soyutlama yaptığımızı düşünebilirsiniz. Fakat bu sınıfları bir CDI ortamında (Spring ya da SEAM gibi) bu interfaceler üzerinden kolayca yönetebilirsiniz. Ayrıca hazırlık kısmında belirttiğimiz API katmanlı yapıya kolaylıkla geçiş yapabilirsiniz. Hatta ve hatta gerekirse Hibernate kısmını söküp yerine başka bir ORM toolunu kolaylıkla getirebilirsiniz.

Takip edemeyenler ve projenin son halini merak edenler için projenin git deposu aşağıdaki gibidir.
Projeleri yaratırken sorun yaşadıysanız, proje yapısına Gir Repo’sundan bakabilirsiniz.

Bir sonraki kısımda artık web servislerinin nasıl yazıldığına geçiyoruz.

End Of Line