TP3.2 — تطبيق CRUD كامل (وضع مستقل)
هذا التمرين يستند إلى نفس التمرين تمامًا كما في TP3.1، ولكن بدون أي كود مقدم. يجب عليك تنفيذ كل شيء بنفسك. إذا واجهت صعوبة، استشر TP3.1 كمرجع.
المدة المقدرة: 2 إلى 3 ساعات
المتطلبات المسبقة: فهم مفاهيم الوحدة 3 (العمارة الطبقية، Spring Data JPA، API REST)
السياق
أنت مطور backend في مدرسة. طُلب منك إنشاء API REST لإدارة الطلاب باستخدام Spring Boot.
ما يجب عليك تسليمه
الخطوة 1 — إنشاء مشروع Spring Boot
- أنشئ مشروع Spring Boot جديد عبر Spring Initializr
- اختر التبعيات اللازمة لـ:
- إنشاء API REST
- استخدام قاعدة بيانات في الذاكرة (H2)
- تنفيذ الاستمرارية JPA
- التحقق من صحة البيانات المدخلة
الخطوة 2 — إنشاء الكيان Student
أنشئ كيان Student مع الحقول التالية:
| الحقل | النوع | القيود |
|---|---|---|
| id | Long | مفتاح أساسي، يتم توليده تلقائيًا |
| firstName | String | إلزامي، بين 2 و50 حرفًا |
| lastName | String | إلزامي، بين 2 و50 حرفًا |
| String | إلزامي، بصيغة بريد إلكتروني صحيحة، فريد | |
| age | Integer | إلزامي، بين 18 و100 |
| program | String | إلزامي (مثال: "علوم الحاسوب"، "هندسة البرمجيات") |
الخطوة 3 — إنشاء Repository
- أنشئ واجهة Repository للكيان
Student - أضف طريقة للتحقق مما إذا كان البريد الإلكتروني موجودًا بالفعل
- أضف طريقة للبحث عن الطلاب حسب البرنامج
الخطوة 4 — إنشاء الخدمة
أنشئ خدمة تنفذ المنطق التجاري التالي:
- استرجاع جميع الطلاب
- استرجاع طالب حسب معرفه — إذا لم يكن الطالب موجودًا، أطلق استثناء مناسب
- إنشاء طالب — تحقق من أن البريد الإلكتروني غير مستخدم بالفعل قبل الحفظ. إذا كان البريد الإلكتروني موجودًا بالفعل، أعد خطأ 409 (Conflict)
- تعديل طالب — تحقق من أن الطالب موجود، ثم قم بتحديث معلوماته
- حذف طالب — تحقق من أن الطالب موجود، ثم قم بحذفه
الخطوة 5 — إنشاء Controller REST
أنشئ Controller يعرض النقاط النهائية التالية:
| طريقة HTTP | URL | الإجراء | كود الإرجاع المتوقع |
|---|---|---|---|
| GET | /api/students | قائمة بجميع الطلاب | 200 OK |
| GET | /api/students/\{id\} | تفاصيل طالب | 200 OK أو 404 Not Found |
| POST | /api/students | إنشاء طالب | 201 Created أو 409 Conflict |
| PUT | /api/students/\{id\} | تعديل طالب | 200 OK أو 404 Not Found |
| DELETE | /api/students/\{id\} | حذف طالب | 204 No Content أو 404 Not Found |
- يجب أن يتم التحقق تلقائيًا من البيانات المرسلة في POST وPUT
- إذا فشل التحقق، أعد كود 400 Bad Request
الخطوة 6 — تكوين قاعدة بيانات H2
- قم بتكوين التطبيق لاستخدام قاعدة بيانات H2 في الذاكرة
- فعّل وحدة التحكم H2 لتمكين عرض البيانات في المتصفح
- يجب أن تكون وحدة التحكم متاحة على URL
/h2-console
الخطوة 7 — اختبار جميع النقاط النهائية
اختبر API الخاص بك باستخدام Postman (أو أداة مكافئة). يجب عليك تنفيذ والتقاط الاختبارات التالية:
- إنشاء 3 طلاب (POST) — تحقق من الكود 201
- قائمة بجميع الطلاب (GET) — تحقق من وجود 3
- استرجاع طالب حسب معرفه (GET) — تحقق من البيانات
- تعديل طالب (PUT) — تغيير برنامجه، تحقق من التحديث
- حذف طالب (DELETE) — تحقق من الكود 204
- إعادة قائمة بجميع الطلاب — تحقق من بقاء 2 فقط
- اختبار الأخطاء:
- GET على معرف غير موجود → 404
- POST مع بريد إلكتروني مستخدم بالفعل → 409
- POST مع بريد إلكتروني غير صالح → 400
- POST مع اسم أول فارغ → 400
تمارين إضافية
إضافة 1 — البحث حسب البرنامج
أضف نقطة نهاية تتيح البحث عن الطلاب حسب البرنامج:
GET /api/students/program/{program}
على سبيل المثال: GET /api/students/program/Informatique يعيد جميع الطلاب في علوم الحاسوب.
إضافة 2 — إحصائيات
أضف نقطة نهاية تعيد الإحصائيات:
GET /api/students/stats
يجب أن يحتوي JSON المعاد على:
- العدد الإجمالي للطلاب
- متوسط العمر
- عدد الطلاب حسب البرنامج
إضافة 3 — الترقيم
عدل نقطة النهاية GET /api/students لدعم الترقيم:
GET /api/students?page=0&size=10&sort=lastName
إضافة 4 — إدارة الأخطاء المركزية
أنشئ مدير استثناءات عالمي يقوم بـ:
- إعادة رسائل خطأ واضحة في JSON
- معالجة الحالات: طالب غير موجود (404)، بريد إلكتروني مكرر (409)، فشل التحقق (400)
تنسيق استجابة الخطأ المتوقع:
{
"status": 404,
"message": "طالب غير موجود بالمعرف: 99",
"timestamp": "2025-01-15T10:30:00"
}
إضافة 5 — الانتقال إلى PostgreSQL
استبدل H2 بـ PostgreSQL:
- أنشئ قاعدة بيانات
studentdbفي PostgreSQL - عدل التكوين للإشارة إلى PostgreSQL
- تحقق من أن البيانات تستمر بعد إعادة تشغيل التطبيق
التسليمات
| # | التسليم | التنسيق |
|---|---|---|
| 1 | الكود المصدري الكامل للمشروع | مستودع Git أو ZIP |
| 2 | لقطات شاشة Postman للاختبارات العشرة (7 + 3 أخطاء) | صور |
| 3 | لقطة شاشة لوحدة التحكم H2 مع البيانات | صورة |
| 4 | إكمال ما لا يقل عن 2 من التمارين الإضافية | كود |
| 5 | إجابات على أسئلة المراجعة (أدناه) | مستند نصي |
أسئلة المراجعة
أجب عن هذه الأسئلة بكلماتك الخاصة:
- ما هي مسؤولية كل طبقة (Controller، Service، Repository)؟
- لماذا نقسم الكود إلى طبقات منفصلة؟
- ما الفرق بين
@RestControllerو@Service؟ - كيف يقوم Spring Data JPA بتوليد استعلامات SQL تلقائيًا؟
- ما هو كود HTTP الذي يجب إرجاعه بعد إنشاء ناجح؟ بعد حذف؟
- لماذا نتحقق من فريدة البريد الإلكتروني في الخدمة وليس فقط في قاعدة البيانات؟
- ماذا يحدث إذا أرسلنا JSON غير صالح إلى Controller؟
- ما الفرق بين
findById()الذي يعيدOptionalوطريقة تعيد الكائن مباشرة؟
معايير التقييم
| المعيار | النقاط |
|---|---|
| تنفيذ العمارة الطبقية بشكل صحيح (Controller → Service → Repository) | 20% |
| كيان Student مع جميع التحقق | 15% |
| Repository مع طرق مخصصة | 10% |
| خدمة مع منطق تجاري كامل (تحقق، استثناءات) | 20% |
| Controller مع 5 نقاط نهاية CRUD وظيفية | 20% |
| اختبارات Postman ناجحة (حالات عادية + حالات خطأ) | 10% |
| تمارين إضافية | 5% |
| المجموع | 100% |
إذا كنت عالقًا، لا تبقَ أكثر من 15 دقيقة على مشكلة. استشر TP3.1 لترى كيف تم ذلك، ثم عد هنا وحاول إعادة التنفيذ دون النظر.