Primefaces LazyDataModel Hibernate 5 ile kullanımı

Primefaces LazyDataModel Hibernate 5 ile kullanımı

Primefaces LazyDataModel

Primefaces Datatable aracında verilerimizin hepsinin aynı anda listelenmemesini isteyebiliriz.Çok veri olduğunda ekranda kilitlenmeler yapacaktır.Bu durumlarda LazyDataModel ile verilerin Datatable aracımıza parça parça gelmesini sağlayabiliriz.Örneğin 1 ile 10 arası 10 ile 20 arası gibi.

LazyDataModel implementi

Hibernate ile lazy load işlemi yapacağım.Hibernate 5 ile createcriteria() metodu deprecated duruma geldi. Ben örneğimde CriteriaBuilder,CriteriaQuery... kullanarak veritabanı sorgularımı çalıştırdım.

Gerekenler

Daha önceki yazımda hibernate ile temel crud işlemlerini göstermiştim(Yazıyı Oku).
Bu yazıdaki projeyi indirelim. Bu proje üzerine ben customer.xhtml, CustomerBean,CustomerService,CustomerDao şeklinde sınıflarımı ekledim.Önceki yazıda Service Dao , beans.xml ile dependency injection kısımlarını detaylı anlatmıştım bu  yazıda lazy data model üzerine yoğunlaşacağım.

 

Customer.xhtml

Customer sayfam için bir datatable aracı kullandım.Burada unutmamanız gereken datatable aracında lazy=true Bu sayede oluşturacağımz LazyDataModel sınıfındali load metodu tetiklenecek ve parça parça veri çekme işlemimiz gerçekleşecek.Bir diğer kısım ise value=bean.lazydatamodel burada önceki örneklerimizden farklı olarak List değil LazyDataModel bağlıyoruz.Her sayfada kaç veri listeleneceğini ayarlamak için rows=”8″ etiketini kullanmalıyız.

	<p:dataTable id="dtCustomer" value="#{customerBean.lazyModelCustomer}" lazy="true" var="customer" editable="true" paginator="true" paginatorPosition="bottom" rows="8" currentPageReportTemplate="{startRecord}-{endRecord} records are listed. Totally: {totalRecords} records" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}">

Customer Xhtml Son hali

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui">

<h:head></h:head>
<body>


	<h:form id="form">
		<p:dataTable id="dtCustomer" value="#{customerBean.lazyModelCustomer}" lazy="true" var="customer" editable="true" paginator="true" paginatorPosition="bottom" rows="8" currentPageReportTemplate="{startRecord}-{endRecord} records are listed. Totally: {totalRecords} records" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}">


			<p:column headerText="ID">
				<h:outputText value="#{customer.personId}" />
			</p:column>
			
			<p:column headerText="First Name" filterBy="#{customer.firstname}" sortBy="#{customer.firstname}">
				<h:outputText value="#{customer.firstname}" />
			</p:column>
			<p:column headerText="Last Name">
				<h:outputText value="#{customer.lastname}" />
			</p:column>
			<p:column headerText="Job">
				<h:outputText value="#{customer.job}" />
			</p:column>
			<p:column headerText="City">
				<h:outputText value="#{customer.city}" />
			</p:column>
			<p:column headerText="Adress">
				<h:outputText value="#{customer.address}" />
			</p:column>
			
		</p:dataTable>

	</h:form>
</body>
</html>

Customer Bean

Bean sayfamızda xhtml ile bağlanılacak lazyDataModelimi başlatmam gerekli.

 
private LazyDataModel<ZzAtakanPerson> lazyModelCustomer;

Sayfa ilk açıldığında ekranda verilerimi görmek istiyorum init() metodunda lazy modelimi başlatıyorum

 
@PostConstruct
	public void init() {
		 lazyModelCustomer = new CustomerLazyDataModel(customerService);
	}

CustomerLazyDataModel

LazyDataModel verilerin parça parça gelmesi için implement edilmesi gereken sınıfımızdır.

getRowKey() : Satır seçme işleminde tekrar etmeyen id  alanımız

getRowData() : rowKey değerine göre parça verideki seçilen satırın entity objesi

load (int first, int pageSize, String sortField, SortOrder sortOrder,Map<String, Object> filters)

load metodu primefaces datatable aracı tarafından çağırılır bu metodda satır sayısı ve data listesini çekmeliyiz.İçindeki parametreleri açıklayalım.

first : Listelenecek verideki ilk satır numarasıdır. 1 ile 10 arasını listele dersek first : 1 , 10 ile 20 arası dediğimizde 20dir.

pageSize: Xhtml sayfasında rows=8 olarak belirttiğimiz yer burasıdır.her sayfada ne kadar eleman olacağı bilgisi

sortField: Sıralama yapılacak kolon bilgisi.Ekranda AD’a göre sırala dendiğinde buraya AD seklinde kolon adı gelir

sortOrder: Ekranda Sıralama yapıldığında Azalana veya Artana bilgisi gelir.ASC veya DESC

filters : Bu alanda ekranda filtre yapılan alanlara göre key value seklinde kolon adı-arama içeriği döner.AD-Atakan gibi..


package com.atakancoban.model;

import java.util.List;
import java.util.Map;

import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

import com.atakancoban.orm.ZzAtakanPerson;
import com.atakancoban.service.CustomerService;

public class CustomerLazyDataModel extends LazyDataModel<ZzAtakanPerson> {

	private static final long serialVersionUID = 1928300515443607970L;
	private CustomerService customerService;

	public CustomerLazyDataModel() {
	}

	public CustomerLazyDataModel(CustomerService customerService) {
		this.customerService = customerService;
	}

	@Override
	public Object getRowKey(ZzAtakanPerson object) {
		return object.getPersonId();
	}

	@Override
	public ZzAtakanPerson getRowData(String rowKey) {
		try {

			@SuppressWarnings("unchecked")
			List<ZzAtakanPerson> list = (List<ZzAtakanPerson>) getWrappedData();
			for (ZzAtakanPerson obj : list) {
				if (obj.getPersonId().toString().equals(rowKey))
					return obj;

			}

		} catch (Exception e) {

			System.out.println("getRowData method error" + e.getMessage());
			e.printStackTrace();
		}

		return null;
	}

	@Override
	public List<ZzAtakanPerson> load(int first, int pageSize, String sortField, SortOrder sortOrder,
			Map<String, Object> filters) {
		List<ZzAtakanPerson> list = null;
		try {

			int rowCount = customerService.getCountOfCustomer(filters);
			this.setRowCount(rowCount);

			list = customerService.getDataOfCustomer(first, pageSize, sortField, sortOrder, filters);
		} catch (Exception e) {
			this.setRowCount(0);
			System.out.println("customarLazyModel LOAD method error" + e.getMessage());
			e.printStackTrace();
		}

		return list;
	}

	public CustomerService getCustomerService() {
		return customerService;
	}

	public void setCustomerService(CustomerService customerService) {
		this.customerService = customerService;
	}

}

CustomerServiceImpl

Servis sınıfında lazy data model için gerekli olan COUNT ve LİST döndüren metodlarımı tanımladım.

 
	@Override
	public List<ZzAtakanPerson> getDataOfCustomer(int first, int pageSize, String sortField, SortOrder sortOrder,
			Map<String, Object> filters) throws Exception {
		return customerDao.getDataOfCustomer(first, pageSize, sortField, sortOrder, filters);
	}

	@Override
	public int getCountOfCustomer(Map<String, Object> filters) throws Exception {
		return customerDao.getCountOfCustomer(filters);
	}

CustomerDaoImpl

GetDataOfCustomer Metodu

Hibernate 5 ile createCriteria() metodu deprecated duruma geldi.

// Criteria crit = session.createCriteria(ZzAtakanPerson.class);

CriteriaBuilder : Query üzerinde like,order gibi düzenlemeler yapmamızı yöneten sınıf
CriteriaQuery<ZzAtakanPerson> : Criteria bizden ne dönecekse o Entity ister.Yani ben bu queryden zzAtakanPerson türünde bir satır veya liste olarak veri döndürebilirim.
Root<ZzAtakanPerson> : Burada root aslında base sorgumuz oluyor. select * from tabloadı.Ihtıyaca göre root üzerinde where,orderby vs yaparak veriler çağırılıyor.
Örneğin : critQuery.select(root); root nesnemiz zzAtakanPerson olduğuna göre (select * from zzAtakanPerson) aslında bu işlem.

Temel olarak veri çekme akışı şu şekilde

critQuery.select(root);
critQuery.where(criteriaBuilder.like(root.get(“KOLONADI”), “%ARA_KELİME%”)); //KOLONADI like işlemi> ARAKELİME
critQuery.orderBy(criteriaBuilder.asc(root.get(“KOLONADI”)));  //Asc olarak KOLONADI alanını sırala

session.createQuery(critQuery).setFirstResult(first).setMaxResults(first + pageSize) .getResultList();// criterai query çalıştır ve first ile (first+pagesize) kadar veri getir (1 ile 10 arasındakiler gibi)

 

@Override
	public List<ZzAtakanPerson> getDataOfCustomer(int first, int pageSize, String sortField, SortOrder sortOrder,
			Map<String, Object> filters) throws Exception {

		List<ZzAtakanPerson> customerList = null;
		try {

			Session session = getCurrentSession();
			//deprecated
			// Criteria crit = session.createCriteria(ZzAtakanPerson.class);

			// new version
			// builder oluştur
			CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
			// tablo ne dönecek entity.class liste veya tek satır dönebilir .
			CriteriaQuery<ZzAtakanPerson> critQuery = criteriaBuilder.createQuery(ZzAtakanPerson.class);
			// select*from entity.class düşün root sorgu
			Root<ZzAtakanPerson> root = critQuery.from(ZzAtakanPerson.class);
			// select root yani select * from entity.class şuan aşağıda
			// where,orderby eklendi
			critQuery.select(root);

			// Where
			if (!filters.isEmpty()) {
				Iterator<Entry<String, Object>> iterator = filters.entrySet().iterator();
				while (iterator.hasNext()) {
					Entry<String, Object> entry = iterator.next();

					critQuery.where(criteriaBuilder.like(criteriaBuilder.upper(root.get(entry.getKey())),
							"%" + entry.getValue().toString().toUpperCase(new Locale("tr", "TR")) + "%"));

				
				
				
					critQuery.where(criteriaBuilder.like(root.get(entry.getKey()),
							"%arakelime%"));
				
				
				}
			}

			// Order By

			if (sortField != null && !sortField.isEmpty()) {
				if (sortOrder.equals(SortOrder.ASCENDING)) {
					// crit = crit.addOrder(Order.asc(sortField));
					// order by - yukarıda select,where yapılmıştır şimdi order
					// eklendi yine criteriabuilder.
					critQuery.orderBy(criteriaBuilder.asc(root.get(sortField)));
				} else {
					// crit = crit.addOrder(Order.desc(sortField));

					critQuery.orderBy(criteriaBuilder.desc(root.get(sortField)));
				}
			}

			// query first , max parameterleri ve getResultList() eski hali
			// list()di
			customerList = session.createQuery(critQuery).setFirstResult(first).setMaxResults(first + pageSize)
					.getResultList();

		} catch (Exception e) {
			throw new Exception("getDataOfCustomer() method error " + e.getMessage(), e);
		}
		return customerList;
	}

GetCountOfCustomer Metodu

Row count için gerekli olan metodumuzda da mantık aynı fakat değişen yerler var

CriteriaQuery<Long> : Burada sorgumuzdan bir entitiy almayacağız sadece rakam alacağız o nedenle Long olarak verdim

Bir değişen yer ise
critQuery.select(criteriaBuilder.count(root)); burada root sorgumuzun sadece sayısını alacağız.criteraiBuilder ile bunu yaptım.

Temel olarak veri çekme akışı

critQuery.select(criteriaBuilder.count(root));
critQuery.where(criteriaBuilder.like(root.get(“KOLONADI”), “%ARA_KELİME%”)); //KOLONADI like işlemi> ARAKELİME

Burada orderBy yok çünkü toplam sayıya etkisi yok sadece where koşulu gerekli

session.createQuery(critQuery).getSingleResult().intValue(); //Sadece rakam döneceği için singleResult

 

@Override
	public int getCountOfCustomer(Map<String, Object> filters) throws Exception {
		int customerTotalCount = 0;
		try {

			Session session = getCurrentSession();

			//deprecated
			// session.createCriteria(ZzAtakanPerson.class).setProjection(Projections.rowCount());

			// Builder oluştur
			CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
			// query oluştur ne dönüyor entitiy.class
			CriteriaQuery<Long> critQuery = criteriaBuilder.createQuery(Long.class);
			// select * from (entity.class) gibi düşün root class
			Root<ZzAtakanPerson> root = critQuery.from(ZzAtakanPerson.class);
			// select cümlesi - builder ile count al , tüm data için root
			// yazılır.
			critQuery.select(criteriaBuilder.count(root));

			// Where
			if (!filters.isEmpty()) {
				Iterator<Entry<String, Object>> iterator = filters.entrySet().iterator();
				while (iterator.hasNext()) {
					Entry<String, Object> entry = iterator.next();

					critQuery.where(criteriaBuilder.like(criteriaBuilder.upper(root.get(entry.getKey())),
							"%" + entry.getValue().toString().toUpperCase(new Locale("tr", "TR")) + "%"));

				}
			}

			
		
			
			Query query = session.createQuery(critQuery);
			// uniqueResult değil getSingleResult() gelen tek veriyi al obje de
			// olabilir
			if (query.getSingleResult() != null) {
				customerTotalCount = ((Long) query.getSingleResult()).intValue();

			} else
				customerTotalCount = 0;
		} catch (Exception e) {
			throw new Exception("getCountOfCustomer() method error " + e.getMessage(), e);
		}

		return customerTotalCount;
	}

 

 

Örnek LazyDataModel Projesi

Filtre Örneği

Filtre ve sıralama yapılmadan datatable durumu

Filtre ve Sıralama YOK
Filtre ve Sıralama YOK

 

 

Filtre olarak “ata” kelimesi yazılı.Datatable durumu.

Filtre : Ata ve Sıralama YOK
Filtre : Ata ve Sıralama YOK

 

Filtre olarak “a” harfi yazılı ve datatable durumu.

Filtre : a ve Sıralama YOK
Filtre : a ve Sıralama YOK

Sıralama Örneği

Azalana sıralama örneği

Filtre YOK Sıralama Var
Filtre YOK Sıralama Var

 

Artana sıralama örneği

LazyDataModel Filtre YOK Sıralama Var
Filtre YOK Sıralama Var

 

 

lazyLoad(“Kolay Gelsin 🙂 “);

Projenin kaynak kodlarını indirebilirsiniz.

jsf,hibernate,primefaces,spring  soru öneri>@ŞükrüÇakmak

 

 

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir