JPA,JSF Ve PrimeFaces'ın MongoDB İle Kullanımı
Yukarıdaki MongoDB&Java bölümünden de bildiğiniz üzere daha MongoDB’nin Java driver’ı ile temel işlemler yapmıştık ve bir de Servlet&JSP kullanarak yapılmış örnek projemiz vardı. Fakat MongoDB Java çatısı altında sadece o şekilde kullanılmak zorunda değil. Sürekli yeni çıkan teknolojilere adapte olmaya çalışan ve onlara uygun yazılımlar çıkarmaya çalışan Java dünyası NoSQL dünyasına da kayıtsız kalmamış ve Java ile NoSQL kullanımını daha kolay hale getirmeye çalışmışlar.
Java dünyası içindeki ORM specificaton’ı olan JPA’nın resmi implementadyonu olan EclipseLink geliştiricileri NoSQL teknolojileri için kütüphane geliştirip bize sunmuşlar. Ben de bu yazıda bu EclipseLink’in NoSQL teknolojisini kullanarak bir kayıt ekleme örneğini yapacağım. Kayıtları listeleme sayfasını da yazdım ancak ona yazı içerisinde değinmeyeceğim. https://github.com/ilkgunel/JsfJpaAndongoDBSampleProject adresinden o kısmı inceleyebilirsiniz. Ayrıca kayıt silme ve güncelleme işlemlerini de yazacağım. Onları yazdığım zaman haberdar olmak için beni Twitter’dan takip edebilirsiniz: https://twitter.com/ilkgunel
Başlayalım …
İlk olarak hangi bağımlılıklara ihtiyacımız var onları görelim.
Aşağıdaki listede 5 adet bağımlılığımız var. JSF’in 2.2.13 numaralı sürümü, PrimeFaces’ın 6 numaralı sürümü projemize ekli. org.eclipse.persistence altındaki JPA ve NoSQL’in 2.6.4 sürümünü ekledik. Bu kütüphaneler kayıt ekleme, çekme vs. işlemlerini basitize edecek. Son olarak da MongoDB’nin Java driver’ını projemize ekledik. JPA ve NoSQL kütüphaneleri işlemlerini bu driver üzerinden yapacaklar. Burada önemli bir nokta mevcut. MongoDB’nin her ne kadar 3 ve üzerinde sürümleri olan Java driver’ı olsa da şu an için bu sürümler EclipseLink’in NoSQL teknolojisi ile uyumlu çalışamıyor. Bu nedenle biz 2.13.0 sürümlü Java drvier’ı kullanıyoruz.
<?xml version="1.0" encoding="UTF-8"?>
<dependencies>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.2.13</version>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>6.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.6.4</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.nosql</artifactId>
<version>2.6.4</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
persistence.xml
persistence.xml dosyamız içerisinde bağlantı kurulacak veritabanına ait bilgileri tanımlıyoruz. Burada veritabanına gönderilecek, alınacak vs. nesnelere ait sınıfların yani Entity sınıflarının
<?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="mongodbPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<class>com.ilkaygunel.jpaandmongodb.entity.Person</class>
<properties>
<property name="eclipselink.target-database"
value="org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform"/>
<property name="eclipselink.nosql.connection-spec"
value="org.eclipse.persistence.nosql.adapters.mongo.MongoConnectionSpec"/>
<property name="eclipselink.nosql.property.mongo.port" value="27017"/>
<property name="eclipselink.nosql.property.mongo.host" value="localhost"/>
<property name="eclipselink.nosql.property.mongo.db" value="mongodatabase"/>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
</persistence-unit>
</persistence>
index.xhtml’den Bir Parça
Projemizin ana sayfasında şöyle bir kayıt formumuz var. Bu kayıt formu doldurulup butonuna tıkladığında MongoDB’ye ilgili bilgiler gönderiliyor.
<h:form>
<p:panelGrid columns="2">
<p:outputLabel value="İsim:"/>
<p:inputText value="#{managedBeanClass.person.name}"/>
<p:outputLabel value="Soyisim:"/>
<p:inputText value="#{managedBeanClass.person.surname}"/>
<p:outputLabel value="Telefon Numarası:"/>
<p:inputMask mask="0(999) 999-99-99" value="#{managedBeanClass.person.phoneNumber}"/>
<p:outputLabel value="Doğum Tarihi:"/>
<p:calendar value="#{managedBeanClass.person.birthDate}" locale="tr"
yearRange="c-70:c+10" navigator="true" mask="true" pattern="dd-MM-yyyy"/>
<p:outputLabel value="Adres Bilgileriniz"/>
<p:outputLabel/>
<p:outputLabel value="Cadde:"/>
<p:inputText value="#{managedBeanClass.address.street}"/>
<p:outputLabel value="Mahalle:"/>
<p:inputText value="#{managedBeanClass.address.neighborhood}"/>
<p:outputLabel value="İlçe:"/>
<p:inputText value="#{managedBeanClass.address.district}"/>
<p:outputLabel value="İl:"/>
<p:inputText value="#{managedBeanClass.address.city}"/>
<p:outputLabel/>
<p:commandButton value="GÖNDER" ajax="false"
action="#{managedBeanClass.saveDataToDatabase}"/>
<p:outputLabel value="#{managedBeanClass.operationMessage}"/>
<p:outputLabel/>
</p:panelGrid>
</h:form>
JSF sayfamız içinde kullanıcıdan birtakım bilgiler alınıyor ve managed bean içindeki saveDataToDatabase metodu ile MongoDB’ye gönderiliyor.
ManagedBeanClass.java
package com.ilkaygunel.jpaandmongodb.bean;
import com.ilkaygunel.jpaandmongodb.entity.Address;
import com.ilkaygunel.jpaandmongodb.entity.Person;
import java.text.ParseException;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
@ManagedBean
@SessionScoped
public class ManagedBeanClass {
private Person person;
private Address address;
private String operationMessage = "";
public ManagedBeanClass() {
person = new Person();
address = new Address();
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getOperationMessage() {
return operationMessage;
}
public void setOperationMessage(String operationMessage) {
this.operationMessage = operationMessage;
}
public void saveDataToDatabase() throws ParseException {
person.setAddress(address);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("mongodbPersistenceUnit");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.persist(person);
em.getTransaction().commit();
operationMessage = "Kayıt Başarı İle Eklendi!";
GetRecordsBean getRecordsBean = new GetRecordsBean();
getRecordsBean.refreshPersonList();
} catch (Exception e) {
operationMessage = "Kayıt eklenirken bir hata meydana geldi! Hata:"+e;
}
finally{
em.close();
emf.close();
}
}
}
Managed bean içerisinde Person,Address ve operationMessage nesnelerimiz ve onlara ait get-set metotları yer alıyor. saveDataToDatabase metodu içerisinde tıpkı klasik veritabanlarında işlem yapar gibi EntityManager nesnesi elde edip bu nesnenin persist metodu ile veritabanına bilgi yolluyoruz.
Person.java
Person entity sınıfımız’da sınıfımızın işaretlendiği bir notasyona dikkat edelim. Entity sınıfımız @NoSql(dataFormat=DataFormatType.MAPPED) notasyonu ile işaretli. Bu notasyon ile JPA’ya ilişkisel olmayan bir veri kaynağı kullandığını söylüyoruz ve Java fieldlar ile MongoDB objeleri arasında mapleme yapmasını söylüyoruz.
Entity içerisinde Address alanına dikkat edersek bu alan Embedded notasyonu ile işaretlenmiş. Yani dökümanda bir alt alanımız olacak.
package com.ilkaygunel.jpaandmongodb.entity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Temporal;
import org.eclipse.persistence.nosql.annotations.DataFormatType;
import org.eclipse.persistence.nosql.annotations.Field;
import org.eclipse.persistence.nosql.annotations.NoSql;
@Entity
@NoSql(dataFormat=DataFormatType.MAPPED)
public class Person implements Serializable {
public Person() {
}
@Id
@GeneratedValue
@Field(name="_id")
private String id;
@Basic
private String name;
@Basic
private String surname;
@Basic
private String phoneNumber;
@Basic
@Temporal(javax.persistence.TemporalType.DATE)
private Date birthDate;
@Embedded
private Address address;
public String getId() {
return id;
}
public void setId(String 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;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
Address.java
Önceki MongoDB yazılarından hatırlayacağınız gibi MongoDB dökümanları içerisinde alt alanlar olabiliyordu. Yani bunlara embedded document deniliyordu. JPA içerisinde embedded dökümanaları tanımlamak için @Embeddable notasyonu getirilmiş. Person.java içerisinde address alanı alt alandı ve onun tanımlandığı Address sınıfı @Embeddable notasyonu ile işaretli.
package com.ilkaygunel.jpaandmongodb.entity;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Embeddable;
import org.eclipse.persistence.nosql.annotations.DataFormatType;
import org.eclipse.persistence.nosql.annotations.NoSql;
@Embeddable
@NoSql(dataFormat=DataFormatType.MAPPED)
public class Address implements Serializable{
@Basic
private String street;
@Basic
private String neighborhood;
@Basic
private String district;
@Basic
private String city;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getNeighborhood() {
return neighborhood;
}
public void setNeighborhood(String neighborhood) {
this.neighborhood = neighborhood;
}
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district = district;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
Ekran Çıktısı
Ana sayfada gelen formu şu şekilde dolduruyorum ve GÖNDER butonuna tıklıyorum.
Bana kaydın başarı ile yapıldığını söyleyen mesaj dönüyor.
MongoDB’nin arayüz programı üzerinden baktığımda da kaydın başarı ile yollandığını görüyorum.
Bu yazıda da bu kadar arkadaşlar. Yazının başında da söylediğim gibi github’daki projeyi güncelleme ve silme işlemleri için de geliştireceğim. Haberdar olmak için Twitter’dan takip etmeyi unutmayın.
Başka bir yazıda görüşene kadar sağlıcakla kalın.
Selam ve Sevgilerimle