12. [TD]: پیادهسازی لایه [DAO] از TD با استفاده از [Spring Data]
کلیدواژهها: معماری چندلایه، اسپرینگ، تزریق وابستگی، API JPA (پایداری جاوا API)، اسپرینگ دیتا.
ما همان رویکرد قبلی را برای پیادهسازی لایه [DAO] از TD دنبال خواهیم کرد.
12.1. Support
![]() |
- در [1]، پوشه [support / chap-12] حاوی پروژه Eclipse برای این فصل است؛
12.2. پروژه اکلیپس
پروژه اکلیپس به شرح زیر خواهد بود:
![]() |
- [elections.dao.config]: شامل کلاس پیکربندی پروژه Spring است؛
- [elections.dao.entities]: شامل اجزای JPA و همچنین کلاس استثناهای پروژه است؛
- [elections.dao.repositories]: شامل رابطهای [CrudRepository] برای جداول [CONF] و [LISTES] است؛
- [elections.dao.service]: شامل پیادهسازی لایه [DAO] است. این همان چیزی است که باید بنویسیم؛
- [elections.dao.console]: شامل یک کلاس تست از نوع [console] است؛
- [pom.xml]: فایل پیکربندی پروژه Maven؛
این پروژه معماری زیر را پیادهسازی میکند:
![]() |
لایه [DAO] تنها لایهای را میبیند که توسط [Spring Data] پیادهسازی شده است.
12.3. پیکربندی Maven
وظیفه: ساخت فایل [pom.xml] برای پروژه.
12.4. اشیاء در لایه [JPA]
![]() |
![]() |
- [ElectionsConfig] مدل شیء مرتبط با یک سطر در جدول [CONF] است؛
- [ListeElectorale] مدل شیء مرتبط با یک سطر در جدول [LISTES] است؛
- [AbstactEntity] کلاس والد دو کلاس قبلی است. این کلاس فیلدهای مشترک [id, version] را که در هر دو کلاس وجود دارند، استخراج میکند؛
- [ElectionsException] کلاس استثنا برای پروژه است؛
12.4.1. کلاس [ElectionsException]
![]() |
کلاس [ElectionsException] استثنای رسیدگینشدهای است که در بخش ۴.۳ توضیح داده شده است.
12.4.2. کلاس [AbstractEntity]
![]() |
کلاس [AbstractEntity] به شرح زیر است:
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;
// ویژگیها
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
protected Long id;
@Version
@Column(name = "VERSION")
protected Long version;
// سازندهها
public AbstractEntity() {
}
public AbstractEntity(Long id, Long version) {
this.id = id;
this.version = version;
}
// اولویتبندی [equals] و [hashcode]
@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;
}
// امضا jSON
public String toString() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
// گیرندهها و تنظیمکنندهها
...
}
این کلاسی است که در بند 11.3.5.2 توصیف شده است، بدون فیلترهای jSON. در اینجا، در واقع، جداول [CONF] و [LISTES] توسط یک رابطه کلید خارجی به هم متصل نیستند. با این حال، وجود چنین رابطهای با حالت [lazy loading] است که فیلترهای jSON را ضروری میسازد.
12.4.3. کلاس [ElectionsConfig]
![]() |
کلاس [ElectionsConfig]، انتیت JPA است که با جدول [CONF] مرتبط میباشد؛
وظیفه: ایجاد کلاس [ElectionsConfig].
12.4.4. کلاس [ListeElectorale]
![]() |
کلاس [ListeElectorale]، موجودیت JPA است که با جدول [LISTES] مرتبط میباشد؛
وظیفه: کلاس [ListeElectorale] را ایجاد کنید.
12.5. لایه [Spring Data]
![]() |
وظیفه: دو رابط را برای [Spring Data] بنویسید تا دو جدول [CONF] و [LISTES] را مدیریت کند؛
12.6. لایه [DAO]
![]() |
رابط [IElectionsDao] برای لایه [DAO] به شرح زیر است:
package dao.service;
import dao.entities.ElectionsConfig;
import dao.entities.ListeElectorale;
public interface IElectionsDao {
// پیکربندی انتخابات
public ElectionsConfig getElectionsConfig();
// فهرست نامزدها
public ListeElectorale[] getListesElectorales();
// بهروزرسانی فهرست نامزدها
public void setListesElectorales(ListeElectorale[] listesElectorales);
}
وظیفه: پیادهسازی [ElectionsDaoJpa] رابط [IElectionsDao].
12.7. پیکربندی پروژه Spring
کلاس [DaoConfig] پروژه Spring را پیکربندی میکند.
وظیفه: کلاس [DaoConfig] را بنویسید
12.8. لایه [console]
![]() |
![]() |
کلاس [Main] کلاس اجرایی زیر است:
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 {
//منبع داده
private static IElectionsDao dao;
public static void main(String[] args) {
//بازیابی کنتکس بهار
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
//بازیابی منبع داده
dao = ctx.getBean(IElectionsDao.class);
// محتویات دو جدول
ElectionsConfig electionsConfig = dao.getElectionsConfig();
ListeElectorale[] listes = dao.getListesElectorales();
//نمایش
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
ctx.close();
}
}
کلاس [Test01] آزمونی برای JUnit است:
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] لایه
@Autowired
private IElectionsDao electionsDao;
@Before
public void init() {
// پاک کردن جدول [LISTES]
// فهرستهای رقیب
ListeElectorale[] listes = electionsDao.getListesElectorales();
// رایهها و کرسیها را روی 0 تنظیم کنید و مقدار 'eliminated' را روی false تنظیم کنید
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]
electionsDao.setListesElectorales(listes);
}
@Test
public void testElections01() {
System.out.println("testElections01-------------------------------------");
//بازیابی پیکربندی انتخابات
ElectionsConfig electionsConfig = electionsDao.getElectionsConfig();
int nbSiegesAPourvoir = electionsConfig.getNbSiegesAPourvoir();
double seuilElectoral = electionsConfig.getSeuilElectoral();
Assert.assertEquals(6, nbSiegesAPourvoir);
Assert.assertEquals(0.05, seuilElectoral, 1E-6);
// فهرستها در انتخابات
ListeElectorale[] listes = electionsDao.getListesElectorales();
//نمایش مقادیر خواندهشده
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]);
}
//آراء و کرسیها به فهرستها تخصیص داده میشوند
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;
}
//این دادهها با استفاده از لایه [dao] پایدارسازی میشوند
electionsDao.setListesElectorales(listes);
//دادهها دوباره خوانده میشوند
ListeElectorale[] listesElectorales2 = electionsDao.getListesElectorales();
//دادههای خواندهشده تأیید میشوند
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]);
}
}
}
وظیفه: اجرای تستهای [console] و [JUnit] روی لایه [DAO] شما.
12.9. ایجاد آرشیو Maven پروژه
طبق مثال بخش 11.3.12، آرشیو Maven پروژه را تولید کنید.












