Java JSF Hibernate ile CRUD İşlemleri(Ekle,Sil,Güncelle ve Listele)
Hibernate ile CRUD(Temel Veri Tabanı) İşlemleri
Gerekenler
1 ) JSF( Java Server Faces) üzerinde Spring Hibernate entegre etmiştik. (Yazıyı Oku)
2 ) Sonra bu proje üzerinde Hibernate Tablo Entity sınıfları üretmeyi anlatmıştım.(Yazıyı Oku)
1 numaralı yazıdan hazır projeyi indirip üzerine 2 numaralı derse göre hibernate Tablo Entity oluşturabilirsiniz.
Hibernate CRUD İşlemleri(Yapılan Örnek)
# Project Name : Hello Jsf # Hibernate Version : 5.2.10.Final # Spring Version : 4.3.10.RELEASE # Java Version : 1.8 # Dynamic Web : 3.1 # Oracle DB : 11G
Örneğimizde veritabanında örnek tablom (ZZ_ATAKAN_PERSON) tablosu üzerinde veri listele, veri güncelle, veri sil ve veri ekle işlemleri yaptım.
1 ) hellojsf/person.xhtml (İlk olarak verilerin listelenmesi)
2 ) Silme Örneği (ID = 109 )
Silme işlemi sonrası tablonun görünümü(109 ID numaralı satır silindi)
3 ) Güncelleme Örneği (110 ID numaralı satır)
Güncelleme Örneği (Satır güncellenmek üzere aktif oldu )
Güncelleme Örneği(110 ID numaralı satır değerleri değiştirildi)
Güncelleme işlemi tamamlandı(110 ID Numaralı satır)
4 ) Satır Ekleme İşlemi
Bunun için form dolduruldu ve btnAddPerson butonu çalıştırıldı.(Altta hazırladığım örnek veri ekleme formu)
Veri Ekleme sonrası tablonun son hali (115 ID Numaralı satır eklendi )
Gördüğünüz gibi örnek sitede hibernate @Entity model sınıfı kullanılarak temel veri tabanı işlemleri yapıldı. Şimdi nasıl yaptığımıza bakalım.
Hibernate ile Veri Tabanı İşlemleri Kod ve Açıklamalar
Öncelikle ben örneğimde Generic Dao implementi kullandım.Resimde görüldüğü gibi Generic Dao sınıfında tüm dao sınıflarımda ortak olarak kullanılacak metodları Generic olarak oluşturdum. Bu sayede yeni DAOlar oluşturduğumuz zaman temel veritabanı işlemlerini tekrar tekrar yazmamıza gerek kalmayacak.
1 ) Dao ve Veri Bağlantıları Kısmı
GenericDao
package com.atakancoban.dao.base; import java.io.Serializable; import java.util.List; public interface GenericDao<T extends Serializable> { long countAll(); List<T> getAll(); Serializable save(T t); void delete(T t); void update(T t); void saveOrUpdate(T t); void saveOrUpdate(List<T> list); void flushAndClear(); void applyChanges(); List<T> getOrderedAsc(String propertyName); List<T> getOrderedDesc(String propertyName); }
GenericDaoImpl
package com.atakancoban.dao.base; import java.io.Serializable; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; import org.springframework.stereotype.Repository; @Repository public abstract class GenericDaoImpl<T extends Serializable> implements Serializable, GenericDao<T> { private static final long serialVersionUID = 1L; private Class<T> persistentClass; private SessionFactory sessionFactory; public GenericDaoImpl(Class<T> persistentClass) { this.persistentClass = persistentClass; } @Override public long countAll() { return getRowCount(getAllRecordsCriteria()); } @SuppressWarnings("unchecked") @Override public List<T> getAll() { List<T> list = getAllRecordsCriteria().list(); System.out.println(persistentClass.getSimpleName() + " getAll() success"); return list; } @Override public Serializable save(T t) { Serializable serializable = getCurrentSession().save(t); System.out.println(persistentClass.getSimpleName() + " save() success"); return serializable; } @Override public void update(T t) { getCurrentSession().update(t); System.out.println(persistentClass.getSimpleName() + " update() success"); } @Override public void saveOrUpdate(T t) { getCurrentSession().saveOrUpdate(t); System.out.println(persistentClass.getSimpleName() + " saveOrUpdate() success"); } @Override public void saveOrUpdate(List<T> list) { getCurrentSession().saveOrUpdate(list); System.out.println(persistentClass.getSimpleName() + " saveOrUpdate(list) success"); } @Override public void delete(T t) { getCurrentSession().delete(t); System.out.println(persistentClass.getSimpleName() + " delete() success"); } @SuppressWarnings("unchecked") @Override public List<T> getOrderedAsc(String propertyName) { return getAllRecordsCriteria().addOrder(Order.asc(propertyName)).list(); } @SuppressWarnings("unchecked") @Override public List<T> getOrderedDesc(String propertyName) { return getAllRecordsCriteria().addOrder(Order.desc(propertyName)).list(); } protected long getRowCount(Criteria criteria) { long rowCount = (Long) criteria.setProjection(Projections.rowCount()).list().get(0); return rowCount; } protected Criteria getAllRecordsCriteria() { Criteria criteria = getCurrentSession().createCriteria(getPersistentClass()); return criteria; } public Class<T> getPersistentClass() { return persistentClass; } protected void setPersistentClass(final Class<T> persistentClass) { this.persistentClass = persistentClass; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } protected SessionFactory getSessionFactory() { return sessionFactory; } protected Session getCurrentSession() { return getSessionFactory().getCurrentSession(); } @Override public void flushAndClear() { getCurrentSession().flush(); getCurrentSession().clear(); } @Override public void applyChanges() { getCurrentSession().flush(); } }
Önceki yazıda Hibernate Tools ile Oluşturduğum @Entity (Yazıyı Oku)
ZzAtakanPerson (Tablo Entitiy)
package com.atakancoban.orm; // Generated Aug 24, 2017 3:28:08 PM by Hibernate Tools 5.2.0.Beta1 import java.math.BigDecimal; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; /** * ZzAtakanPerson generated by hbm2java */ @Entity @Table(name = "ZZ_ATAKAN_PERSON", schema = "FCBSADM") public class ZzAtakanPerson implements java.io.Serializable { private BigDecimal personId; private String lastname; private String firstname; private String address; private String city; private String job; public ZzAtakanPerson() { } public ZzAtakanPerson(BigDecimal personId) { this.personId = personId; } public ZzAtakanPerson(BigDecimal personId, String lastname, String firstname, String address, String city, String job) { this.personId = personId; this.lastname = lastname; this.firstname = firstname; this.address = address; this.city = city; this.job = job; } @Id @Column(name = "PERSON_ID", unique = true, nullable = false, precision = 22, scale = 0) public BigDecimal getPersonId() { return this.personId; } public void setPersonId(BigDecimal personId) { this.personId = personId; } @Column(name = "LASTNAME", length = 30) public String getLastname() { return this.lastname; } public void setLastname(String lastname) { this.lastname = lastname; } @Column(name = "FIRSTNAME", length = 30) public String getFirstname() { return this.firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } @Column(name = "ADDRESS", length = 200) public String getAddress() { return this.address; } public void setAddress(String address) { this.address = address; } @Column(name = "CITY", length = 100) public String getCity() { return this.city; } public void setCity(String city) { this.city = city; } @Column(name = "JOB", length = 100) public String getJob() { return this.job; } public void setJob(String job) { this.job = job; } }
Veri Tabanı işlemlerimi yapmak için PersonDao isminde bir dao oluşturdum ve bu dao ZzAtakanPerson tablosu için oluştu yani bu tablo ile ilgili ekleme silme güncelleme gibi işlemleri PersonDao üzerinden yapacağım. PersonDao sınıfımda GenericDao sınıfından extends olduğu için generic dao içindeki save(),update() gibi metodlarıma buradan ulaşacağım.Kod tekrarı yapmama gerek yok.
PersonDao
package com.atakancoban.dao; import com.atakancoban.dao.base.GenericDao; import com.atakancoban.orm.ZzAtakanPerson; public interface PersonDao extends GenericDao<ZzAtakanPerson> { }
PersonDaoImpl
package com.atakancoban.dao; import java.io.Serializable; import org.springframework.stereotype.Repository; import com.atakancoban.dao.base.GenericDaoImpl; import com.atakancoban.orm.ZzAtakanPerson; @Repository("personDao") public class PersonDaoImpl extends GenericDaoImpl<ZzAtakanPerson> implements PersonDao, Serializable { private static final long serialVersionUID = 1036158609629705297L; public PersonDaoImpl() { super(ZzAtakanPerson.class); } }
2 ) Hibernate Config (Connection bilgileri)
testcon.xml
Burada @Entity sınıfımızı <mapping class="com.atakancoban.orm.ZzAtakanPerson" /> sessionFactory içinde hibernate ile bağlıyoruz.
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory name="sessionFactory"> <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> <property name="connection.driver_class">oracle.jdbc.OracleDriver</property> <property name="connection.url">jdbc:oracle:thin:@İPADRESİ:1521:SID</property> <property name="connection.username">USERNAME</property> <property name="connection.password">PASSWORD</property> <property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property> <property name="hibernate.c3p0.acquire_increment">1</property> <property name="hibernate.c3p0.idle_test_period">0</property> <property name="hibernate.c3p0.min_size">1</property> <property name="hibernate.c3p0.max_size">15</property> <property name="hibernate.c3p0.timeout">0</property> <property name="show_sql">true</property> <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property> <mapping class="com.atakancoban.orm.ZzAtakanPerson" /> </session-factory> </hibernate-configuration>
3 ) Beans Xml ile İlişkilendirme Kısmı
beans-atakan-coban.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"> <bean id="genericDao" class="com.atakancoban.dao.base.GenericDaoImpl" abstract="true"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="personDao" class="com.atakancoban.dao.PersonDaoImpl" parent="genericDao" /> <bean id="carDao" name="carDao" class="com.atakancoban.dao.CarDaoImpl"> <property name="sessionFactory" ref="sessionFactory" /> </bean> </beans>
Dao sınıflarında interface ve implement edilmiş bir sınıf gördük. Spring tarafından Dependency Injection özelliği ile buradaki xml kısmında Dao ve DaoImpl sınıflarını tanıtıyoruz.<property> şeklinde ise @Autowired şeklinde çağırıldı anda setter olarak gönderilecek değişkeni gönderebiliyoruz.Detaylı anlatalım
beans içindeki genericDao tanımı burada bir yerden
@Autowired
GenericDao genericdao;
Şeklinde çağırıldığında beans xmldeki ilişkisine göre genericDaoImp metodlarını çağırabilir durumda geliyor.<property> olarak verilen session factory de o sınıfe gönderiliyor. Bu sayede her dao için session yollamamıza gerek kalmıyor.Dependency Injection ile metodu çalışmaya hazır halde sınıfımızı alıyoruz. PersonDao beans xmlde parent özelliğine genericDao yazdık metodlara ve sessiona ulaşıyoruz.
Ben örneğimde PersonDao ile çalıştığım için PersonService sınıfımda bu şekilde çağırdım
@Autowired
PersonDao personDao;
Bu sayede generic daodaki metodlara ve sessiona ulaştım.
4 ) Service ve Transactional Kısmı
PersonService
package com.atakancoban.service; import java.util.List; import com.atakancoban.orm.ZzAtakanPerson; public interface PersonService { List<ZzAtakanPerson> getPersonList() throws Exception; void deletePerson(ZzAtakanPerson entity) throws Exception; void updatePerson(ZzAtakanPerson entity) throws Exception; void addPerson(ZzAtakanPerson entity) throws Exception; }
Burada @Transactional(readOnly = true) annotationu bir metodun başında belirtmediğim sürece o metodun sadece veri çekeceğini belirtiyor.Gereksiz yere rollback yapılacak gibi transaction açmaya gerek yok.
Rollback(örneğin veri eklenirken hata oluştu birazı eklendi eski hale dönme işlemi diyebiliriz.) gereken metodlarda
@Transactional(rollbackFor = Exception.class, readOnly = false)
Şeklinde annotation belirterek veritabanına ekleme vs işlemlerde hata oluşmamışsa işlemi uygulamasını sağladım.
PersonServiceImpl
package com.atakancoban.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.atakancoban.dao.PersonDao; import com.atakancoban.orm.ZzAtakanPerson; @Service("personService") @Transactional(readOnly = true) public class PersonServiceImpl implements PersonService { @Autowired private PersonDao personDao; @Override public List<ZzAtakanPerson> getPersonList() throws Exception { return personDao.getOrderedAsc("personId"); } public PersonDao getPersonDao() { return personDao; } public void setPersonDao(PersonDao personDao) { this.personDao = personDao; } @Transactional(rollbackFor = Exception.class, readOnly = false) @Override public void deletePerson(ZzAtakanPerson entity) throws Exception { personDao.delete(entity); personDao.flushAndClear(); } @Transactional(rollbackFor = Exception.class, readOnly = false) @Override public void updatePerson(ZzAtakanPerson entity) throws Exception { personDao.update(entity); personDao.flushAndClear(); } @Transactional(rollbackFor = Exception.class, readOnly = false) @Override public void addPerson(ZzAtakanPerson entity) throws Exception { personDao.save(entity); personDao.flushAndClear(); } }
5 ) Bean ve Xhtml Kısmı
Person Xhtml
<!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="dtPerson" value="#{personBean.listPersonEntity}" var="person" editable="true" paginator="true" paginatorPosition="bottom" rows="8" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"> <p:ajax event="rowEdit" listener="#{personBean.onRowEdit}" update=":form:dtPerson" /> <p:column headerText="Person ID" sortBy="#{person.personId}" filterBy="#{person.personId}"> <h:outputText value="#{person.personId}" /> </p:column> <p:column headerText="First Name"> <p:cellEditor> <f:facet name="output"> <h:outputText value="#{person.firstname}" /> </f:facet> <f:facet name="input"> <p:inputText value="#{person.firstname}" style="width:90%" /> </f:facet> </p:cellEditor> </p:column> <p:column headerText="Last Name"> <p:cellEditor> <f:facet name="output"> <h:outputText value="#{person.lastname}" /> </f:facet> <f:facet name="input"> <p:inputText value="#{person.lastname}" style="width:90%" /> </f:facet> </p:cellEditor> </p:column> <p:column headerText="Job"> <p:cellEditor> <f:facet name="output"> <h:outputText value="#{person.job}" /> </f:facet> <f:facet name="input"> <p:inputText value="#{person.job}" style="width:90%" /> </f:facet> </p:cellEditor> </p:column> <p:column headerText="City"> <p:cellEditor> <f:facet name="output"> <h:outputText value="#{person.city}" /> </f:facet> <f:facet name="input"> <p:inputText value="#{person.city}" style="width:90%" /> </f:facet> </p:cellEditor> </p:column> <p:column headerText="Adress"> <p:cellEditor> <f:facet name="output"> <h:outputText value="#{person.address}" /> </f:facet> <f:facet name="input"> <p:inputText value="#{person.address}" style="width:90%" /> </f:facet> </p:cellEditor> </p:column> <p:column headerText="Delete"> <p:commandButton value="Delete" actionListener="#{personBean.onDelete(person)}" update=":form:dtPerson" /> </p:column> <p:column headerText="Update"> <p:rowEditor /> </p:column> </p:dataTable> <p:panelGrid columns="1"> <p:inputText placeholder="Firstname" value="#{personBean.firstname}" /> <p:inputText placeholder="Lastname" value="#{personBean.lastname}" /> <p:inputText placeholder="Job" value="#{personBean.job}" /> <p:inputText placeholder="City" value="#{personBean.city}" /> <p:inputText placeholder="Adress" value="#{personBean.adress}" /> </p:panelGrid> <p:commandButton value="btnAddPerson" update=":form:dtPerson" actionListener="#{personBean.onAddPerson()}" /> </h:form> </body> </html>
Bu sayfasında datatable oluşturdum.value=”#{personBean.listPersonEntity}” veritabanından çektiğim verileri burada listeledim.loadTable() metodu ile bean > service > dao sıralaması ile verinin ekrana gelmesini sağladım
Bean sınıfımda oluşturduğum actionListener=”#{personBean.onDelete(person)}” metodu ile bean > service > dao sırası ile çağırılmasını sağladım ve silme işlemi yaptım.
Güncelleme işlemi için <p:rowEditor /> kullandım. Bu araç değişikliği onayla (tik ikonu) basıldığında
<p:ajax event=”rowEdit” listener=”#{personBean.onRowEdit}” update=… şeklinde event çalıştırır.Burada onRowEdit metodum benim Bean> Service >Dao şeklinde veritabanında güncelleme işlemini yaptırmamı sağladı.
Peki bu update ne oluyor ?
Primefaces araçları arkaplanda yapılan değişikliği göstermek için update edilmelidir.
Araçlar update edilmezse metod çalışıyor ama veriler değişmiyor diyebilirsiniz..
Update için aşağıdaki formatta istediğiniz aracı update edebilirsiniz.person xhtml içinde update nerelerde yapılmış bakmayı unutmayın
update=”:formAdı:araçID“
PersonBean
xhtml tarafından erişlen sayfamız beandir.Xhtml aracı db işlemi için Bean > Service > Dao sıralamasında metod zinciri çalıştırır.
package com.atakancoban.bean; import java.io.Serializable; import java.math.BigDecimal; import java.util.List; import javax.annotation.PostConstruct; import javax.faces.bean.ManagedBean; import javax.faces.bean.ManagedProperty; import org.primefaces.event.RowEditEvent; import org.springframework.web.context.annotation.SessionScope; import com.atakancoban.orm.ZzAtakanPerson; import com.atakancoban.service.PersonService; @ManagedBean(name = "personBean") @SessionScope public class PersonBean implements Serializable { private static final long serialVersionUID = -8162090623891464980L; private List<ZzAtakanPerson> listPersonEntity; @ManagedProperty(value = "#{personService}") private PersonService personService; private String firstname, lastname, job, city, adress; @PostConstruct public void init() { try { loadTable(); } catch (Exception e) { System.out.println("init() Error. " + e.getMessage()); e.printStackTrace(); } } public void onDelete(ZzAtakanPerson entity) { try { personService.deletePerson(entity); System.out.println(entity.getPersonId().longValue()); loadTable(); } catch (Exception e) { System.out.println("onDelete() Error. " + e.getMessage()); e.printStackTrace(); } } public void onRowEdit(RowEditEvent event) { try { ZzAtakanPerson entity = (ZzAtakanPerson) event.getObject(); personService.updatePerson(entity); loadTable(); } catch (Exception e) { System.out.println("onRowEdit() Error. " + e.getMessage()); e.printStackTrace(); } } public void onAddPerson() { try { ZzAtakanPerson entity = new ZzAtakanPerson(); entity.setFirstname(firstname); entity.setLastname(lastname); entity.setJob(job); entity.setCity(city); entity.setAddress(adress); entity.setPersonId(new BigDecimal(00)); personService.addPerson(entity); loadTable(); } catch (Exception e) { System.out.println("onAddPerson() Error. " + e.getMessage()); e.printStackTrace(); } } public void loadTable() throws Exception { listPersonEntity = personService.getPersonList(); } // *****Getter - Setter****** }
Projenin kaynak kodlarını github hesabımdan indirebilirsiniz
Jsf,Spring Framework ve Hibernate ile uzmanlık gerektiren sorular için > Şükrü Çakmak