JavaFX ile EclipseLink(ORM) kullanarak CRUD islemleri yapmak

javafx
  • Turgay Can
  • Tarih

    24 Apr, 2013
  • Yorum

    0
  • Görüntüleme

    1998
  • İndirme

    25

JavaFX ile EclipseLink(ORM) kullanarak CRUD islemleri yapmak

Merhaba,

Bir kaç aydır zaman bulup tam olarak tamamlayıp, yayınlayamadığım FX yazımı paylaşayım. Yazı FX ile ORM (Object Related Mapping) kullanarak basit CRUD işlemleri yapmak olacak.

Uygumala NetBeans 7.3 IDE üzerinde geliştirilmiştir. ORM aracı olarak EclipseLink kullanılmıştır. Database olarak ise
embeded Java Derby DB kullanıldı. FXML ile arayüzler inşa edildi ve arayüzde TextFiled, Button ve TableView bileşenleri kullanıldı.

Uygulamada basit bir öğrenci kaydı girilmesi, tablo içinde listelenmesi ve tablodan seçili olan öğrencinin silinme işlemleri mevcuttur.

Hemen uygulamamıza dönelim. Öncelikle Projects sekmesinde boş alanda sağ tuş yapıp açılan menüden sırasıyla ; New Project.. -> JavaFX -> JavaFx FXML Application'ı seçiyoruz. next butonuna basıyoruz gelen ekranda proje ismin verelim burada "FXCrudWithORM" olarak verdim. JavaFx Platform sekmesinde kurulu olan FX Platformunuzu seçip, Finish butonuna basınız. FX uygulamamızı oluşturmuş olduk.

Daha sonra Services kısmında Database altındaki Java DB servisi içinde, APP şeması altında, Tables üzerinde sağ tuş yapınız açılan menüden Execute Command.. sekmesini seçiniz, sizin için IDe üzerinde SQL yazabileceğiniz pencere açacaktır. Bu pencere içinde Student tablomuzu aşağıdaki SQL cümlesi ile yaratalım.

CREATE TABLE "STUDENT"
    (
    "ID" INT not null primary key
            GENERATED ALWAYS AS IDENTITY
            (START WITH 1, INCREMENT BY 1),   
    "NAME" VARCHAR(50),     
    "EMAIL" VARCHAR(50),
    "DESCRIPTON" VARCHAR(50)
    );

SQL'i çalıştırdığımızda tablomuz yaratılmış olacaktır.

Şimdi sırasıyla uygulamamız için gerekli kütüphaneleri NetBeans IDE içinden ekleyelim. Bunun için ; Projemizin içindeki Libraries üzerinde sağ tuş yapınız,
açılan menüden Add Library.. sekmesini seçiniz, sırasıyla EclipseLink (JPA 2.0) ve Java DB driver'ı seçiniz. Aşağıdaki imajdaki gibi projenize eklenmesi gerekli.

JavaFX ile EclipseLink(ORM) kullanarak CRUD işlemleri yapmak

EclipseLink ile beraber persistence.xml'imiz gelecektir. O sırada database servisinizin açık olması önerilir böylelikle anlık olarak database servisi üzerinden tablomuzu EclipseLink ORM ile sınıf olarak yaratırmış oluruz.

persistence.xml

   <?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="FXCrudWithORMPU" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <class>fxcrudwithorm.Student</class>
        <properties>
          <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/FXDB"/>
          <property name="javax.persistence.jdbc.password" value="app"/>
          <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
          <property name="javax.persistence.jdbc.user" value="app"/>
          <property name="eclipselink.jdbc.native-sql" value="true"/>
          <property name="eclipselink.logging.thread" value="true"/>
          <property name="eclipselink.logging.timestamp" value="true"/>
        </properties>
      </persistence-unit>
    </persistence>

Student.java

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author turgay.can
 */
@Entity
@Table(name = "STUDENT")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Student.findAll", query = "SELECT s FROM Student s"),
    @NamedQuery(name = "Student.findById", query = "SELECT s FROM Student s WHERE s.id = :id"),
    @NamedQuery(name = "Student.findByName", query = "SELECT s FROM Student s WHERE s.name = :name"),
    @NamedQuery(name = "Student.findByEmail", query = "SELECT s FROM Student s WHERE s.email = :email"),
    @NamedQuery(name = "Student.findByDescription", query = "SELECT s FROM Student s WHERE
 s.description = :description")})
public class Student implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "ID")
    private Integer id;
    @Column(name = "NAME")
    private String name;
    @Column(name = "EMAIL")
    private String email;
    @Column(name = "DESCRIPTION")
    private String description;    

    public Student() {
    }

    public Student(Integer id) {
        this.id = id;
    }
    //getters, setters
    .
    .
    .
}

Böylelikle ORM taraflı işimiz bitmiş oluyor. Şimdi FX kısmına geçelim ve hem FXML dizaynımızı hemde Controller sınıfımızı yazalım.
Aşağıdaki imajdaki gibi bir dizaynı Scene Builder aracı inşa ettim.
JavaFX ile EclipseLink(ORM) kullanarak CRUD işlemleri yapmak

Sample.fxml

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

        <?import java.lang.*?>
        <?import java.util.*?>
        <?import javafx.scene.*?>
        <?import javafx.scene.control.*?>
        <?import javafx.scene.control.cell.*?>
        <?import javafx.scene.layout.*?>
        <?import javafx.scene.text.*?>

        <AnchorPane id="AnchorPane" prefHeight="491.0" prefWidth="574.0" xmlns:fx="http://javafx.com/fxml" 
    fx:controller="fxcrudwithorm.SampleController">
          <children>
            <Label fx:id="label" layoutX="39.0" layoutY="47.0" minHeight="16.0" minWidth="69.0"
 prefHeight="180.0" prefWidth="332.0" />
            <TextField fx:id="txtName" layoutX="159.0" layoutY="59.0" prefWidth="200.0"
 promptText="Ör : Turgay" />
            <TextField fx:id="txtEmail" layoutX="159.0" layoutY="102.0" prefWidth="200.0" 
promptText="Ör :[email protected]" />
            <TextField fx:id="txtAciklama" layoutX="159.0" layoutY="149.0" prefWidth="200.0"
 promptText="Opsiyonel" />
            <Button fx:id="btnKaydet" layoutX="289.0" layoutY="187.0" mnemonicParsing="false"
 onAction="#kaydet"   text="Kaydet" textOverrun="CENTER_ELLIPSIS">
              <font>
                <Font name="System Bold" size="14.0" fx:id="x1" />
              </font>
            </Button>
            <Label layoutX="70.0" layoutY="62.0" text="Ad" />
            <Label layoutX="70.0" layoutY="105.0" text="Email" />
            <Label layoutX="70.0" layoutY="152.0" text="Açıklama" />
            <TableView fx:id="stuTable" editable="true" layoutX="14.0" layoutY="246.0" 
prefHeight="200.0" prefWidth="442.0"   tableMenuButtonVisible="true">
              <columns>
                <TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="71.0" text="ID" fx:id="idCol">
                  <cellValueFactory>
                    <PropertyValueFactory property="id" />
                  </cellValueFactory>
                </TableColumn>
                <TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="110.0" text="Ad" fx:id="firstNameCol">
                  <cellValueFactory>
                    <PropertyValueFactory property="name" />
                  </cellValueFactory>
                </TableColumn>
                <TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="122.0" text="Email" fx:id="emailCol">
                  <cellValueFactory>
                    <PropertyValueFactory property="email" />
                  </cellValueFactory>
                </TableColumn>
                <TableColumn maxWidth="5000.0" minWidth="10.0" prefWidth="131.0" text="Açıklama" fx:id="descCol">
                  <cellValueFactory>
                    <PropertyValueFactory property="description" />
                  </cellValueFactory>
                </TableColumn>
              </columns>
            </TableView>
            <Label layoutX="118.0" layoutY="461.0" text="http://www.kodlapaylas.com/programlama/javafx-p1.html">
              <font>
                <Font name="System Bold" size="12.0" />
              </font>
            </Label>
            <Label layoutX="159.0" layoutY="16.0" text="www.kodlapaylas.com">
              <font>
                <Font name="System Bold" size="16.0" />
              </font>
            </Label>
            <Button fx:id="btnSil" font="$x1" onAction="#sil" layoutX="480.0" layoutY="246.0" 

mnemonicParsing="false" prefWidth="70.0" text="Sil" />

FXML kısmında yeni farkettiğim ve hoşuma giden bir özellik ise promptText="Opsiyonel" özelliği :) Oldukça bilgilendirici ve yönlendirici olmuş.

SampleController kısmında Sample.fxml(view)'ın kontrollerini yazalım. Aşağıda kod içerisinde comment'ler ile her metod'un ne iş yaptığını açıkladım.
Kod içinden takip ediniz.

SampleController.java

import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.swing.JOptionPane;

/**
 * Table View için yararlandığım kaynak
 * 
 * http://docs.oracle.com/javafx/2/ui_controls/table-view.htm
 *
 * @author turgay.can
 */
public class SampleController implements Initializable {

    //FXML içinde kullandığım bileşenlerin fx:id'lerinin birebir 
    //controller sınıfında aşağıdaki gibi aynı olması dikkat ediniz
    //
    @FXML
    private TextField txtName, txtEmail, txtAciklama;
    @FXML
    private TableView stuTable;
    @FXML
    private TableColumn idCol, firstNameCol, emailCol, descCol;
    //EclipseLink JPA Entitymanager nesnesi
    private EntityManager entityManager;
    //tableView içinde database'deki gelen verinin doldurulması için gerekli data structure'ımız
    ObservableList data;

    @FXML
    private void kaydet(ActionEvent event) {
        try {
            if (validateKayitForm()) {
                entityManager = javax.persistence.Persistence.createEntityManagerFactory("FXCrudWithORMPU").
createEntityManager();
                entityManager.getTransaction().begin();
                Student student = new Student();
                student.setName(txtName.getText());
                student.setEmail(txtEmail.getText());
                student.setDescription(txtAciklama.getText());
                entityManager.persist(student);
                entityManager.getTransaction().commit();
                doldurTablo();
                JOptionPane.showMessageDialog(null, "Başarılı bir şekilde kaydedildi!");
            } else {
                JOptionPane.showMessageDialog(null, "Kayıt formundaki bütün alanları doldurunuz!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            entityManager.getTransaction().rollback();
        } finally {
            if (entityManager.isOpen()) {
                entityManager.close();
            }
        }
    }

    @FXML
    private void sil(ActionEvent event) {
        try {
            //Tablo üzerinde seçilen satırın elde edilmesi ve Student nesnesine dönüşümü
            Student student = (Student) stuTable.getSelectionModel().getSelectedItem();
            if (student != null) {
                entityManager = javax.persistence.Persistence.createEntityManagerFactory("FXCrudWithORMPU").
``createEntityManager();
                entityManager.getTransaction().begin();
                student = entityManager.getReference(Student.class, student.getId());
                entityManager.remove(student);
                entityManager.getTransaction().commit();
                JOptionPane.showMessageDialog(null, "Kayıt başarıl ıbir şekilde tablodan silindi!");
                doldurTablo();
            } else {
                JOptionPane.showMessageDialog(null, "Kayıt silmek için Tablodan silmek istediğiniz satırı seçiniz!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            entityManager.getTransaction().rollback();
        } finally {
            if (entityManager.isOpen()) {
                entityManager.clear();
            }
        }
    }

     //Kayıt formu içindeki TextField'lerin boş ve null kontrolü
    boolean validateKayitForm() {       
        if (txtName.getText().trim().length() > 0 && txtName.getText().trim().length() < 50
                && txtEmail.getText().trim().length() > 0 && txtEmail.getText().trim().length() < 50
                && txtAciklama.getText().trim().length() > 0 && txtAciklama.getText().trim().length() < 50) {
            return true;
        } else {
            return false;
        }
    }

    void doldurTablo() {
        try {
            data = FXCollections.observableArrayList();

            //FXMl içindeki Tablo'nun header'larının tanımlanması
            idCol = new TableColumn("ID");
            idCol.setMinWidth(50);
            idCol.setCellValueFactory(
                    new PropertyValueFactory("id"));

            firstNameCol = new TableColumn("Ad");
            firstNameCol.setMinWidth(50);
            firstNameCol.setCellValueFactory(
                    new PropertyValueFactory("name"));

            emailCol = new TableColumn("Email");
            emailCol.setMinWidth(50);
            emailCol.setCellValueFactory(
                    new PropertyValueFactory("email"));

            descCol = new TableColumn("Açıklama");
            descCol.setMinWidth(70);
            descCol.setCellValueFactory(
                    new PropertyValueFactory("description"));
            //EntityManager ile ORM üzerinden database'e bağlantısı
            entityManager = javax.persistence.Persistence.createEntityManagerFactory("FXCrudWithORMPU").
``createEntityManager();
            //İşlem yapmak için transaction metodunun begin metodu ile açılması
            entityManager.getTransaction().begin();
            //createnamedQuery ile Student.java içerisinde tanımlanmış query'mizin çağrılması
            Query query = entityManager.createNamedQuery("Student.findAll");
            //Çağrılan query'nin liste olarak geri dönmesi ve Singleton FXCollections nesnesi
            //içine doldurulması ve ObservableList içine atanması
            ObservableList lst = FXCollections.observableArrayList(query.getResultList());
            //lst içine atanan yapılandırılmış verilerin TableView içine doldurulması
            stuTable.setItems(lst);
            //transaction'ın kapatılması
            entityManager.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            entityManager.getTransaction().rollback();
        } finally {
            if (entityManager.isOpen()) {
                //açık kalana bağlantının kapatılması
                entityManager.close();
            }
        }

    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
        //Program açıldığında doldurTablo metodu ile TableView bileşeni için varolan verileri dolduruyoruz
        //Eğer veri yoksa content doesnot exist gibi bir uyarı veriyordu yanlış hatırlamyıorsam
          doldurTablo();
    }
}

Muhtemel olaylar ve sonrası ekran çıktıları;

JavaFX ile EclipseLink(ORM) kullanarak CRUD işlemleri yapmak

JavaFX ile EclipseLink(ORM) kullanarak CRUD işlemleri yapmak

İyi çalışmalar :)

0 Yorum..

Yorum yapmak için "Giriş yapın" yada "Misafir üye" olarak yorum yapabilirsiniz.

Yorum Yap