ModelMapper في Java: دليل شامل لتعيين الكائنات تلقائياً
1. ما هو ModelMapper ولماذا تحتاجه؟
ModelMapper هي مكتبة قوية للغة Java، مصممة لتحويل (تعيين) الكائنات من نوع إلى آخر تلقائياً. في التطوير الحديث، خاصة عند استخدام بنية متعددة الطبقات (Controller ← Service ← Repository)، يواجه المطورون باستمرار الحاجة لنسخ البيانات بين DTO (كائنات نقل البيانات) و Entity (كيانات قاعدة البيانات) و VO (كائنات القيمة) و POJO الأخرى. كتابة هذا الكود يدوياً هي مهمة شاقة وعرضة للأخطاء، مما يؤدي إلى تضخم الكود وتقليل سهولة قراءته.
الهدف الرئيسي من ModelMapper هو تخليص المطور من كتابة الكود النمطي مثل source.getField() ← target.setField(). تقوم المكتبة بتحليل بنية الفئات (الحقول، دوال الجلب/التعيين) وتطابقها تلقائياً باستخدام اتفاقيات التسمية (convention over configuration). وهي تدعم الكائنات المتداخلة، والمجموعات، والوراثة، والتحويلات المعقدة، مما يجعلها أداة لا غنى عنها في تطبيقات Java المؤسسية.
ModelMapper مفيد بشكل خاص في السيناريوهات التالية:
- طبقات التطبيق: تحويل Entity إلى DTO والعكس لنقل البيانات عبر REST API.
- الخدمات المصغرة: تعيين الكائنات بين الخدمات المختلفة.
- إعادة الهيكلة: عندما يتغير هيكل الفئات، يكفي تعديل التعيين في مكان واحد.
- الاختبار: إنشاء بيانات اختبارية بسرعة بناءً على كائنات موجودة.
2. التثبيت
يتم توزيع ModelMapper عبر Maven Central. لتثبيته، يجب إضافة التبعية إلى ملف pom.xml (لـ Maven) أو build.gradle (لـ Gradle).
Maven (pom.xml):
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.2.0</version>
</dependency>
Gradle (build.gradle):
implementation 'org.modelmapper:modelmapper:3.2.0'
ملاحظة: الإصدار 3.2.0 هو الأحدث وقت كتابة المقال. يُنصح بالتحقق من أحدث إصدار على MVNRepository.
3. بداية سريعة — مثال عملي بسيط
لنأخذ مثالاً بسيطاً: لدينا كلاس UserEntity (كيان قاعدة بيانات) و UserDTO (كائن لنقل البيانات).
// الكلاس الأصلي (Entity)
public class UserEntity {
private Long id;
private String firstName;
private String lastName;
private String email;
// المنشئات، دوال الجلب والتعيين
public UserEntity() {}
public UserEntity(Long id, String firstName, String lastName, String email) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
// الكلاس الهدف (DTO)
public class UserDTO {
private Long id;
private String fullName; // لاحظ: اسم الحقل مختلف
private String emailAddress;
// المنشئات، دوال الجلب والتعيين
public UserDTO() {}
public Long getId() { return id; }
public void