Skip to content

12. [TD]: [DAO] katmanının TD ile [Spring Data] kullanılarak uygulanması

Anahtar kelimeler: çok katmanlı mimari, Spring, bağımlılık enjeksiyonu, API JPA (Java Persistence API), Spring Data.

TD'in [DAO] katmanını uygulamak için önceki adımlarla aynı süreci izleyeceğiz.

12.1. Support

  • [1]'te, [support / chap-12] klasörü bu bölümün Eclipse projesini içerir;

12.2. Eclipse projesi

Eclipse projesi şu şekilde olacaktır:

  
  • [elections.dao.config]: Spring projesinin yapılandırma sınıfını içerir;
  • [elections.dao.entities]: JPA varlıklarını ve projenin istisna sınıfını içerir;
  • [elections.dao.repositories]: [CONF] ve [LISTES] tabloları için [CrudRepository] arayüzlerini içerir;
  • [elections.dao.service]: [DAO] katmanının uygulamasını içerir. Yazmamız gereken bu sınıftır;
  • [elections.dao.console]: [console] türünde bir test sınıfı içerir;
  • [pom.xml]: Maven projesinin yapılandırma dosyasıdır;

Bu proje aşağıdaki mimariyi uygular:

[DAO] katmanı, yalnızca [Spring Data] tarafından uygulanan katmanı görür.

12.3. Maven Yapılandırması


Yapılması gereken iş: Projenin [pom.xml] dosyasını derleyin.


12.4. [JPA] katmanındaki varlıklar

  
  • [ElectionsConfig], [CONF] tablosundaki bir satıra ait nesne modelidir;
  • [ListeElectorale], [LISTES] tablosundaki bir satıra ait nesne modelidir;
  • [AbstactEntity], önceki iki sınıfın üst sınıfıdır. Bu sınıf, her iki sınıfa ortak olan [id, version] alanlarını bir araya getirir;
  • [ElectionsException], projenin istisna sınıfıdır;

12.4.1. [ElectionsException] sınıfı

  

[ElectionsException] sınıfı, 4.3. paragrafında açıklanan kontrol edilemeyen istisnadır.

12.4.2. [AbstractEntity] sınıfı

  

[AbstractEntity] sınıfı şöyledir:


package elections.dao.entities;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@MappedSuperclass
public abstract class AbstractEntity implements Serializable{
    private static final long serialVersionUID = 1L;

    // özellikler
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    protected Long id;
    @Version
    @Column(name = "VERSION")
    protected Long version;

    // yapıcılar
    public AbstractEntity() {

    }

    public AbstractEntity(Long id, Long version) {
        this.id = id;
        this.version = version;
    }

    // [equals] ve [hashcode] yeniden tanımlama
    @Override
    public int hashCode() {
        return (id != null ? id.hashCode() : 0);
    }

    @Override
    public boolean equals(Object entity) {
        if (!(entity instanceof AbstractEntity)) {
            return false;
        }
        String class1 = this.getClass().getName();
        String class2 = entity.getClass().getName();
        if (!class2.equals(class1)) {
            return false;
        }
        AbstractEntity other = (AbstractEntity) entity;
        return id != null && this.id == other.id;
    }

    // imza jSON
    public String toString() {
        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.writeValueAsString(this);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

    // alıcı ve ayarlayıcılar
...
}

Bu, 11.3.5.2. paragrafında açıklanan sınıftır, ancak jSON filtreleri hariçtir. Burada, [CONF] ve [LISTES] tabloları bir yabancı anahtar ilişkisi ile birbirine bağlı değildir. Oysa [lazy loading] modu ile böyle bir ilişkinin varlığı, jSON filtrelerinin gerekliliğini ortaya çıkarır.

12.4.3. [ElectionsConfig] sınıfı

  

[ElectionsConfig] sınıfı, [CONF] tablosuyla ilişkili JPA varlığıdır;


Yapılması gereken iş: [ElectionsConfig] sınıfını oluşturun.


12.4.4. [ListeElectorale] sınıfı

  

[ListeElectorale] sınıfı, [LISTES] tablosuyla ilişkili JPA varlığıdır;


Yapılması gereken iş: [ListeElectorale] sınıfını oluşturun.


12.5. [Spring Data] katmanı

  

Yapılması gereken iş: [Spring Data] sınıfının, [CONF] ve [LISTES] tablolarını yönetmek için gerekli iki arayüzünü yazın;


12.6. [DAO] katmanı

  

[DAO] katmanının [IElectionsDao] arayüzü şu şekildedir:


package dao.service;

import dao.entities.ElectionsConfig;
import dao.entities.ListeElectorale;

public interface IElectionsDao {

    // seçim yapılandırması
    public ElectionsConfig getElectionsConfig();

    // aday listeleri
    public ListeElectorale[] getListesElectorales();

    // aday listelerinin güncellenmesi
    public void setListesElectorales(ListeElectorale[] listesElectorales);
}

Yapılması gereken iş: [IElectionsDao] arayüzünün [ElectionsDaoJpa] uygulamasını yazın.


12.7. Spring projesinin yapılandırılması

  

[DaoConfig] sınıfı, Spring projesini yapılandırır.


Yapılması gereken iş: [DaoConfig] sınıfını yazın


12.8. [console] katmanı

  

[Main] sınıfı, aşağıdaki yürütülebilir sınıftır:


package dao.console;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import dao.config.AppConfig;
import dao.entities.ElectionsConfig;
import dao.entities.ListeElectorale;
import dao.service.IElectionsDao;

public class Main {

    // veri kaynağı
    private static IElectionsDao dao;

    public static void main(String[] args) {
        // Spring bağlamının alınması
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        // veri kaynağının alınması
        dao = ctx.getBean(IElectionsDao.class);
        // iki tablonun içeriği
        ElectionsConfig electionsConfig = dao.getElectionsConfig();
        ListeElectorale[] listes = dao.getListesElectorales();
        // görüntüleme
        System.out.println(String.format("Nombre de sièges à pourvoir : %d", electionsConfig.getNbSiegesAPourvoir()));
        System.out.println(String.format("Seuil électoral : %5.2f", electionsConfig.getSeuilElectoral()));
        System.out.println("Listes candidates----------------");
        for (ListeElectorale liste : listes) {
            System.out.println(liste);
        }
        // Spring bağlamının kapatılması
        ctx.close();
    }

}

[Test01] sınıfı, JUnit'in bir testidir:


package dao.tests;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import dao.config.AppConfig;
import dao.entities.ElectionsConfig;
import dao.entities.ListeElectorale;
import dao.service.IElectionsDao;

@SpringApplicationConfiguration(classes = AppConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class Test01 {

    // [DAO] katmanı
    @Autowired
    private IElectionsDao electionsDao;

    @Before
    public void init() {
        // [LISTES] tablosu temizleniyor
        // rekabet halindeki listeler
        ListeElectorale[] listes = electionsDao.getListesElectorales();
        // oy ve koltuk sayılarını 0'a sıfırlayıp false olarak siliniyor
        int voix = 0;
        int sièges = 0;
        boolean elimine = false;
        for (ListeElectorale liste : listes) {
            liste.setVoix(voix);
            liste.setSieges(sièges);
            liste.setElimine(elimine);
        }
        // [dao] katmanı sayesinde bu verileri kalıcı hale getiriyoruz
        electionsDao.setListesElectorales(listes);
    }

    @Test
    public void testElections01() {
        System.out.println("testElections01-------------------------------------");
        // seçim yapılandırmasının alınması
        ElectionsConfig electionsConfig = electionsDao.getElectionsConfig();
        int nbSiegesAPourvoir = electionsConfig.getNbSiegesAPourvoir();
        double seuilElectoral = electionsConfig.getSeuilElectoral();
        Assert.assertEquals(6, nbSiegesAPourvoir);
        Assert.assertEquals(0.05, seuilElectoral, 1E-6);

        // yarışan listeler
        ListeElectorale[] listes = electionsDao.getListesElectorales();
        // okunan değerlerin görüntülenmesi
        System.out.println("Nombre de sièges à pourvoir : " + nbSiegesAPourvoir);
        System.out.println("Seuil électoral : " + seuilElectoral);
        System.out.println("Listes en compétition ---------------------");
        for (int i = 0; i < listes.length; i++) {
            System.out.println(listes[i]);
        }

        // listelere oy ve sandalye tahsis ediliyor
        int voix = 0;
        int sièges = 0;
        boolean elimine = false;
        for (ListeElectorale liste : listes) {
            liste.setVoix(voix);
            liste.setSieges(sièges);
            liste.setElimine(elimine);
            voix += 10;
            sièges += 1;
            elimine = !elimine;
        }

        // bu veriler [dao] katmanı aracılığıyla kalıcı hale getiriliyor
        electionsDao.setListesElectorales(listes);

        // veriler yeniden okunur
        ListeElectorale[] listesElectorales2 = electionsDao.getListesElectorales();
        // okunan veriler kontrol edilir
        Assert.assertEquals(7, listesElectorales2.length);
        voix = 0;
        sièges = 0;
        elimine = false;
        for (ListeElectorale liste : listes) {
            Assert.assertEquals(voix, liste.getVoix());
            Assert.assertEquals(sièges, liste.getSieges());
            Assert.assertEquals(elimine, liste.isElimine());
            voix += 10;
            sièges += 1;
            elimine = !elimine;
        }
        System.out.println("Listes en compétition ---------------------");
        for (int i = 0; i < listes.length; i++) {
            System.out.println(listes[i]);
        }
    }
}

Yapılması gereken iş: [console] ve [JUnit] testlerini [DAO] katmanınızda çalıştırın.


12.9. Projenin Maven arşivinin oluşturulması

11.3.12 numaralı paragrafta verilen örneği takip ederek, projenin Maven arşivini oluşturun.