MapStruct হল একটি কোড জেনারেশন টুল যা Java Beans এর মধ্যে ডেটা ম্যাপিং সহজ এবং দ্রুত করার জন্য ব্যবহৃত হয়। Mapper Interface হল MapStruct এর একটি মূল অংশ যা ডেটা ম্যাপিং করার জন্য ব্যবহৃত হয়। Mapper Interface তৈরি করার মাধ্যমে, আপনি দুটি Java Beans (যেমন DTO এবং Entity ক্লাস) এর মধ্যে ডেটা ট্রান্সফরমেশন কনফিগার করতে পারেন।
এই টিউটোরিয়ালে, আমরা MapStruct Mapper Interface তৈরি করার পদ্ধতি এবং এর ব্যবহার আলোচনা করব।
১. MapStruct Mapper Interface কী?
MapStruct Mapper Interface হল একটি ইন্টারফেস যা দুটি ক্লাসের মধ্যে ডেটা ম্যাপিংয়ের জন্য ব্যবহৃত হয়। আপনি এই ইন্টারফেসে একটি বা একাধিক মেথড ডিফাইন করেন, যেগুলি এক ক্লাস থেকে অন্য ক্লাসে ডেটা স্থানান্তরের কাজ করবে। MapStruct তখন এই ইন্টারফেসের জন্য কোড জেনারেট করে, যা ডেটা ট্রান্সফরমেশন করবে।
২. Mapper Interface তৈরি করার পদ্ধতি
এখানে, আমরা একটি Person এবং PersonDTO ক্লাসের মধ্যে ডেটা ট্রান্সফরমেশন করার জন্য একটি Mapper Interface তৈরি করব।
২.১ Step 1: Person এবং PersonDTO ক্লাস তৈরি করা
Person.java:
public class Person { private String firstName; private String lastName; private int age; // Getters and Setters 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 int getAge() { return age; } public void setAge(int age) { this.age = age; } }PersonDTO.java:
public class PersonDTO { private String firstName; private String lastName; // Getters and Setters 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; } }
এখানে, Person এবং PersonDTO ক্লাস দুটি রয়েছে, যেগুলোর মধ্যে ডেটা ট্রান্সফরমেশন করার জন্য MapStruct ব্যবহার করা হবে।
২.২ Step 2: Mapper Interface তৈরি করা
এখন, আমরা Mapper Interface তৈরি করব যা Person এবং PersonDTO ক্লাসের মধ্যে ডেটা ম্যাপ করবে।
PersonMapper.java:
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface PersonMapper {
// Mapper instance
PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
// Method to map Person to PersonDTO
PersonDTO personToPersonDTO(Person person);
// Method to map PersonDTO to Person
Person personDTOToPerson(PersonDTO personDTO);
}
এখানে:
@Mapper: এই অ্যানোটেশন MapStruct কে নির্দেশ করে যে এটি একটি Mapper Interface। MapStruct এই ইন্টারফেসটির জন্য কোড জেনারেট করবে।Mappers.getMapper(): এটি MapStruct দ্বারা কোড জেনারেট করার জন্য একটি ইনস্ট্যান্স তৈরি করে।personToPersonDTO: এটিPersonক্লাসের ডেটা PersonDTO তে ট্রান্সফার করবে।personDTOToPerson: এটিPersonDTOক্লাসের ডেটা Person তে ট্রান্সফার করবে।
MapStruct এখানে একটি কনক্রিট ইমপ্লিমেন্টেশন ক্লাস তৈরি করবে (যেমন, PersonMapperImpl), যা ম্যাপিংয়ের কাজ করবে।
২.৩ Step 3: MapStruct এর জন্য প্রয়োজনীয় ডিপেনডেন্সি যুক্ত করা
MapStruct ব্যবহারের জন্য আপনাকে MapStruct এবং MapStruct Processor ডিপেনডেন্সি pom.xml ফাইলে যুক্ত করতে হবে।
pom.xml:
<dependencies>
<!-- MapStruct API -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<!-- MapStruct Processor -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
এখানে, mapstruct লাইব্রেরি API প্রদান করে, এবং mapstruct-processor ডিপেনডেন্সি কোড জেনারেট করার জন্য প্রয়োজনীয়।
২.৪ Step 4: Mapper Interface ব্যবহার করা
এখন, আমরা Mapper Interface ব্যবহার করে ডেটা ট্রান্সফরমেশন করব।
Main.java:
public class Main {
public static void main(String[] args) {
// Creating a Person object
Person person = new Person();
person.setFirstName("John");
person.setLastName("Doe");
person.setAge(30);
// Mapping Person to PersonDTO
PersonDTO personDTO = PersonMapper.INSTANCE.personToPersonDTO(person);
// Outputting the mapped PersonDTO
System.out.println("First Name: " + personDTO.getFirstName());
System.out.println("Last Name: " + personDTO.getLastName());
// Mapping PersonDTO back to Person
Person personFromDTO = PersonMapper.INSTANCE.personDTOToPerson(personDTO);
// Outputting the mapped Person object
System.out.println("Person from DTO - First Name: " + personFromDTO.getFirstName());
System.out.println("Person from DTO - Last Name: " + personFromDTO.getLastName());
}
}
এখানে, আমরা PersonMapper.INSTANCE.personToPersonDTO(person) কল করে Person অবজেক্টকে PersonDTO তে ম্যাপ করেছি, এবং তারপর PersonDTO কে Person তে রিভার্স ম্যাপিং করেছি।
৩. MapStruct এর সুবিধা
- Compile-time validation: MapStruct কোড জেনারেশন করার সময় টাইপ সেফটি নিশ্চিত করে, তাই runtime এ ত্রুটি হওয়া কম হয়।
- No Reflection: এটি runtime এ reflection ব্যবহার না করায় পারফরম্যান্স অনেক দ্রুত।
- Customizable Mapping: আপনি কাস্টম ম্যাপিং, কাস্টম কনভার্টার এবং ডেটা ট্রান্সফরমেশন লজিক খুব সহজে কনফিগার করতে পারেন।
সারাংশ
MapStruct একটি শক্তিশালী টুল যা Java Beans এর মধ্যে ডেটা ট্রান্সফরমেশন করার জন্য ব্যবহৃত হয়। Mapper Interface তৈরি করার মাধ্যমে, আপনি ডেটা ম্যাপিং স্বয়ংক্রিয়ভাবে পরিচালনা করতে পারেন, যেখানে MapStruct কোড জেনারেট করে। এটি compile-time ম্যাপিং সিস্টেম ব্যবহার করে, যার ফলে পারফরম্যান্স দ্রুত হয় এবং runtime তে কোনো অতিরিক্ত কার্যক্রমের প্রয়োজন হয় না। MapStruct একটি অত্যন্ত কার্যকরী সমাধান যখন আপনি DTO এবং Entity এর মধ্যে ডেটা স্থানান্তর করতে চান।
MapStruct একটি powerful Java লাইব্রেরি যা ডোমেইন অবজেক্ট থেকে DTO (Data Transfer Object) অথবা অন্য যেকোনো অবজেক্টে ডেটা ম্যাপিং বা কনভার্সন সহজ করে তোলে। MapStruct স্বয়ংক্রিয়ভাবে কোড জেনারেট করার মাধ্যমে compile-time এ ডেটা কনভার্সন প্রক্রিয়া সম্পন্ন করে, ফলে এটি রানটাইম পারফরম্যান্সে অতিরিক্ত ওভারহেড সৃষ্টি করে না। MapStruct এর মাধ্যমে ডেটা ম্যাপিং করার জন্য Mapper Interface ব্যবহার করা হয়।
এই টিউটোরিয়ালে, আমরা Mapper Interface এর ভূমিকা এবং এর কার্যকারিতা সম্পর্কে বিস্তারিত আলোচনা করব।
১. Mapper Interface কি?
Mapper Interface হল একটি বিশেষ ধরনের interface যা MapStruct ব্যবহারের জন্য তৈরি করা হয়। এটি মূলত @Mapper অ্যানোটেশন ব্যবহার করে ডিজাইন করা হয়, যা MapStruct কে জানিয়ে দেয় যে এটি একটি ম্যাপিং ইন্টারফেস এবং এর মধ্যে থাকা মেথডগুলির মাধ্যমে অবজেক্টগুলির মধ্যে ডেটা কনভার্সন করা হবে।
এটি MapStruct এর মূল উপাদান, যা ডোমেইন অবজেক্ট এবং DTO (বা অন্য অবজেক্ট) এর মধ্যে ডেটা কনভার্সন সম্পাদন করতে ব্যবহৃত হয়।
২. Mapper Interface এর ভূমিকা
Mapper Interface এর মাধ্যমে আপনি MapStruct কে বলে দেন কোন দুটি অবজেক্টের মধ্যে ডেটা ট্রান্সফার করতে হবে এবং কোন ফিল্ডগুলো ম্যাপ করতে হবে। এটি এমন একটি Interface যা MapStruct দ্বারা @Mapper অ্যানোটেশন ব্যবহার করে স্পষ্টভাবে ডোমেইন অবজেক্টগুলির মধ্যে ম্যাপিং সম্পর্কিত লজিক নির্ধারণ করে।
Mapper Interface এর প্রধান ভূমিকা:
- Data Mapping: Mapper Interface ডোমেইন অবজেক্ট এবং DTO এর মধ্যে ডেটা কপি করতে ব্যবহৃত হয়। এটি ডেটা ট্রান্সফার অবজেক্ট (DTO) এবং Entity ক্লাসের মধ্যে কনভার্সন বাস্তবায়ন করে।
- Auto Code Generation: MapStruct এই ইন্টারফেসের ভিত্তিতে কোড জেনারেট করে, ফলে আপনাকে কোন কনভার্সন কোড লিখতে হয় না।
- Custom Mapping Logic: Mapper Interface কাস্টম ম্যাপিংয়ের জন্য মেথড তৈরি করতে পারে, যেমন
expressionব্যবহার করে কাস্টম কনভার্সন ফাংশন যোগ করা।
৩. Mapper Interface এর উদাহরণ
ধরা যাক, আমাদের দুটি ক্লাস রয়েছে: Car (ডোমেইন অবজেক্ট) এবং CarDTO (ডেটা ট্রান্সফার অবজেক্ট)। আমরা MapStruct ব্যবহার করে এই দুটি ক্লাসের মধ্যে ডেটা ম্যাপ করতে চাই।
৩.১ Car.java (Domain Object)
public class Car {
private String make;
private String model;
private int year;
// Getters and Setters
}
৩.২ CarDTO.java (DTO)
public class CarDTO {
private String make;
private String model;
// Getters and Setters
}
৩.৩ CarMapper.java (Mapper Interface)
এখন, MapStruct এর মাধ্যমে Car থেকে CarDTO তে ডেটা ম্যাপ করার জন্য আমাদের একটি Mapper Interface তৈরি করতে হবে:
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface CarMapper {
// MapStruct কে জানিয়ে দেয় যে এটি ম্যাপিং ইন্টারফেস
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
// Mapping method
CarDTO carToCarDTO(Car car);
}
এখানে, @Mapper অ্যানোটেশন দিয়ে আমরা MapStruct কে জানাচ্ছি যে এটি একটি ম্যাপিং ইন্টারফেস। এই ইন্টারফেসের মধ্যে carToCarDTO মেথড ডোমেইন অবজেক্ট Car থেকে DTO CarDTO তে ডেটা ম্যাপ করবে।
৩.৪ Main.java (Usage Example)
public class Main {
public static void main(String[] args) {
// Creating Car instance
Car car = new Car();
car.setMake("Toyota");
car.setModel("Corolla");
car.setYear(2020);
// Using MapStruct to map Car to CarDTO
CarDTO carDTO = CarMapper.INSTANCE.carToCarDTO(car);
// Print CarDTO
System.out.println("Car Make: " + carDTO.getMake());
System.out.println("Car Model: " + carDTO.getModel());
}
}
এখানে, আমরা CarMapper.INSTANCE.carToCarDTO(car) মেথডটি ব্যবহার করে Car থেকে CarDTO তে ডেটা ম্যাপ করছি। MapStruct স্বয়ংক্রিয়ভাবে ম্যাপিং কোড জেনারেট করবে।
৪. MapStruct Mapper Interface এর সুবিধা
- কোডের পুনঃব্যবহারযোগ্যতা: Mapper Interface আপনাকে কোড পুনরায় ব্যবহারযোগ্যভাবে তৈরি করতে সাহায্য করে।
- অটোমেটিক কোড জেনারেশন: MapStruct compile-time এ কোড জেনারেট করে, যা আপনাকে ম্যাপিং কোড লেখার ঝামেলা থেকে মুক্তি দেয়।
- কাস্টম ম্যাপিং: Mapper Interface ব্যবহার করে কাস্টম ম্যাপিং তৈরি করা যায়, যেমন একটি ফিল্ডের মান কনভার্ট করা বা একটি কাস্টম লজিক প্রয়োগ করা।
- পারফরম্যান্স: MapStruct runtime reflection ব্যবহার না করে, এতে compile-time code generation ব্যবহার করে, তাই এটি পারফরম্যান্সে আরও দক্ষ।
৫. Custom Mapping in Mapper Interface
MapStruct আপনাকে কাস্টম ম্যাপিং লজিক সংযোজন করতে সাহায্য করে। যেমন, যদি আপনি চান CarDTO এর year ফিল্ডকে কাস্টম ফরম্যাটে প্রদর্শন করতে, তবে আপনি এমন কাস্টম ফাংশন ব্যবহার করতে পারেন।
৫.১ Custom Mapping Example
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
@Mapping(target = "year", expression = "java(car.getYear() - 2000)")
CarDTO carToCarDTO(Car car);
}
এখানে, year ফিল্ডের জন্য কাস্টম কনভার্সন ফাংশন ব্যবহার করা হয়েছে, যা year থেকে 2000 বিয়োগ করবে।
৬. Spring Integration with Mapper Interface
MapStruct সহজে Spring Framework এর সাথে ইন্টিগ্রেট করা যায়। আপনি যদি @Mapper এ componentModel = "spring" যোগ করেন, তবে MapStruct আপনাকে Spring Beans হিসেবে Mapper ইন্টারফেস তৈরি করতে সাহায্য করবে। Spring এর মাধ্যমে আপনি Mapper কে ইনজেক্ট করতে পারেন।
৬.১ Spring Integration Example
@Mapper(componentModel = "spring")
public interface CarMapper {
CarDTO carToCarDTO(Car car);
}
এখানে, componentModel = "spring" ব্যবহারের মাধ্যমে CarMapper Spring Bean হিসেবে ব্যবহৃত হবে এবং Spring এর মধ্যে সহজে ইনজেক্ট করা যাবে।
সারাংশ
Mapper Interface হল MapStruct এর একটি গুরুত্বপূর্ণ উপাদান যা ডেটা কনভার্সনের জন্য একটি গাইডলাইন তৈরি করে। এটি @Mapper অ্যানোটেশন ব্যবহার করে তৈরি করা হয় এবং MapStruct এর মাধ্যমে অটোমেটিকভাবে ম্যাপিং কোড জেনারেট করতে সহায়তা করে। MapStruct Mapper Interface ব্যবহার করে ডোমেইন অবজেক্ট থেকে DTO তে বা অন্য অবজেক্টে ডেটা ম্যাপিং করতে পারে। এটি টাইপ সেফ এবং উচ্চ পারফরম্যান্স সমাধান প্রদান করে, বিশেষ করে compile-time কোড জেনারেশন ব্যবহার করার মাধ্যমে।
MapStruct হল একটি জনপ্রিয় Java লাইব্রেরি যা ডেটা ম্যাপিং বা অবজেক্ট কনভার্সন সহজ এবং দ্রুত সম্পন্ন করার জন্য ব্যবহৃত হয়। এটি compile-time code generation ব্যবহার করে, যার ফলে runtime পারফরম্যান্সে কোনো প্রভাব পড়ে না। @Mapper অ্যানোটেশন MapStruct এর সবচেয়ে গুরুত্বপূর্ণ অ্যানোটেশন, যা ম্যাপিং ইন্টারফেসে ব্যবহার করা হয় এবং এর মাধ্যমে মডেল ম্যাপিং সম্পর্কিত কার্যাবলী সম্পাদন করা হয়।
এই টিউটোরিয়ালে, আমরা @Mapper অ্যানোটেশন এর ব্যবহার এবং তার বিভিন্ন বৈশিষ্ট্য আলোচনা করব।
১. @Mapper অ্যানোটেশন কি?
@Mapper অ্যানোটেশন MapStruct লাইব্রেরির একটি প্রধান অ্যানোটেশন, যা একটি interface বা abstract class এর মধ্যে ব্যবহার করা হয়। এটি ডোমেইন অবজেক্টের মধ্যে ডেটা ম্যাপিং বা কনভার্সন প্রক্রিয়াটি পরিচালনা করে। যখন আপনি @Mapper অ্যানোটেশন ব্যবহার করেন, MapStruct কোড জেনারেট করে যা নির্দিষ্ট ফিল্ডগুলির মধ্যে ডেটা কপি করবে।
উদাহরণ:
ধরা যাক, আমাদের দুটি ক্লাস রয়েছে — Person এবং PersonDTO — এবং আমরা Person অবজেক্ট থেকে PersonDTO তে ডেটা ম্যাপ করতে চাই।
public class Person {
private String firstName;
private String lastName;
private int age;
// getters and setters
}
public class PersonDTO {
private String fullName;
private int age;
// getters and setters
}
এখন, MapStruct ব্যবহার করে, firstName এবং lastName ফিল্ডগুলোকে fullName এ কনভার্ট করা হবে।
২. @Mapper অ্যানোটেশন ব্যবহার করে ডেটা ম্যাপিং
MapStruct ব্যবহার করার জন্য প্রথমে একটি Mapper Interface তৈরি করতে হবে, যেখানে @Mapper অ্যানোটেশন ব্যবহার করা হবে।
উদাহরণ: Basic Mapper Interface
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
PersonDTO personToPersonDTO(Person person);
}
এখানে:
@Mapper: এই অ্যানোটেশন MapStruct কে জানায় যে এটি একটি ম্যাপিং ইন্টারফেস।Mappers.getMapper(): এটি MapStruct এর মাধ্যমেPersonMapperইন্টারফেসের একটি ইনস্ট্যান্স তৈরি করে।
২.১ Mapper Interface এর কার্যপদ্ধতি:
এখন, PersonMapper ইন্টারফেসের personToPersonDTO() মেথডটি Person অবজেক্ট থেকে PersonDTO অবজেক্টে ডেটা ম্যাপ করবে।
৩. @Mapper অ্যানোটেশনের অন্যান্য বৈশিষ্ট্য
৩.১ componentModel অ্যানোটেশন:
MapStruct এর @Mapper অ্যানোটেশনে componentModel প্রপার্টি ব্যবহার করে আপনি এটি Spring বা অন্য কোনো ফ্রেমওয়ার্কের সাথে ইন্টিগ্রেট করতে পারেন। যদি আপনি Spring ব্যবহার করতে চান, তবে আপনি componentModel = "spring" সেট করতে পারেন। এটি MapStruct কে Spring Bean হিসাবে কাজ করতে নির্দেশ দেয়।
উদাহরণ: Spring Integration
@Mapper(componentModel = "spring")
public interface PersonMapper {
PersonDTO personToPersonDTO(Person person);
}
এখানে, componentModel = "spring" এর মাধ্যমে PersonMapper একটি Spring Bean হিসাবে তৈরি হবে, যা Spring Container দ্বারা ইনজেক্ট করা যাবে।
৩.২ @Mapping অ্যানোটেশন ব্যবহার করা:
@Mapper এর মাধ্যমে আপনি field mappings নির্দিষ্ট করতে পারেন। আপনি যেভাবে ফিল্ডগুলির মধ্যে ডেটা ম্যাপ করতে চান, তা @Mapping অ্যানোটেশন ব্যবহার করে কনফিগার করতে পারবেন।
উদাহরণ: Field Mapping
@Mapper
public interface PersonMapper {
@Mapping(source = "firstName", target = "fullName")
PersonDTO personToPersonDTO(Person person);
}
এখানে, @Mapping অ্যানোটেশন ব্যবহার করে firstName ফিল্ডটি fullName ফিল্ডে ম্যাপ করা হচ্ছে।
৩.৩ @Mapping এবং Expression Based Mapping:
কখনও কখনও আপনি কাস্টম mapping expressions ব্যবহার করতে চাইতে পারেন, যেখানে আপনি Java expressions ব্যবহার করে ডেটা ম্যাপ করতে পারেন।
উদাহরণ: Expression Based Mapping
@Mapper
public interface PersonMapper {
@Mapping(target = "fullName", expression = "java(person.getFirstName() + \" \" + person.getLastName())")
PersonDTO personToPersonDTO(Person person);
}
এখানে, expression ব্যবহার করে firstName এবং lastName এর মধ্যে স্পেস দিয়ে fullName তৈরি করা হচ্ছে।
৪. MapStruct এবং Collection Mapping
MapStruct List বা Set এর মতো Collection টাইপের ডেটা ম্যাপিং সমর্থন করে। আপনি একটি List অবজেক্টকে অন্য List বা Set এ ম্যাপ করতে পারেন।
উদাহরণ: Collection Mapping
@Mapper
public interface PersonMapper {
List<PersonDTO> personListToPersonDTOList(List<Person> personList);
}
এখানে, List থেকে List তে ডেটা ম্যাপ হচ্ছে।
৫. কাস্টম কনভার্টার ব্যবহার করা
MapStruct কাস্টম কনভার্টার ব্যবহার করার সুবিধাও প্রদান করে, যেখানে আপনি নিজস্ব লজিক প্রয়োগ করতে পারেন।
উদাহরণ: Custom Converter
@Mapper
public interface PersonMapper {
@Mapping(source = "birthDate", target = "birthYear", qualifiedByName = "convertToYear")
PersonDTO personToPersonDTO(Person person);
@Named("convertToYear")
default int convertToYear(Date birthDate) {
return birthDate.getYear();
}
}
এখানে, @Named অ্যানোটেশন ব্যবহার করে একটি কাস্টম কনভার্টার তৈরি করা হয়েছে যা birthDate থেকে birthYear তৈরি করবে।
৬. @Mapper এবং Default Methods
MapStruct ইন্টারফেসে default methods সমর্থন করে, যার মাধ্যমে আপনি কিছু লজিক বাস্তবায়ন করতে পারেন যা ম্যাপিংয়ের অংশ।
উদাহরণ: Default Method
@Mapper
public interface PersonMapper {
PersonDTO personToPersonDTO(Person person);
default String getFullName(String firstName, String lastName) {
return firstName + " " + lastName;
}
}
এখানে, default method ব্যবহার করা হয়েছে যা firstName এবং lastName এর মধ্যে স্পেস দিয়ে fullName তৈরি করবে।
সারাংশ
MapStruct একটি শক্তিশালী এবং টাইপ-সেফ Object Mapping লাইব্রেরি যা Java Beans বা DTO এবং Entity এর মধ্যে ডেটা কনভার্সন অটোমেটিকভাবে সম্পন্ন করতে ব্যবহৃত হয়। @Mapper অ্যানোটেশনটি MapStruct এর মূল বৈশিষ্ট্য, যা ম্যাপিং ইন্টারফেস হিসেবে কাজ করে। এটি ফিল্ড ম্যাপিং, কাস্টম কনভার্সন, স্প্রিং ইন্টিগ্রেশন এবং কাস্টম এক্সপ্রেশন সমর্থন করে, যা ডেটা কনভার্সনকে আরো নমনীয় এবং কার্যকরী করে তোলে।
MapStruct হল একটি কোড জেনারেটর লাইব্রেরি যা source এবং target অবজেক্টগুলির মধ্যে ডেটা ম্যানিপুলেশন বা ম্যাপিং অত্যন্ত সহজভাবে এবং দ্রুতভাবে সম্পন্ন করতে ব্যবহৃত হয়। এটি compile-time কোড জেনারেটিং টুল হিসেবে কাজ করে, ফলে runtime এ অতিরিক্ত পারফরম্যান্স খরচ নেই। MapStruct ব্যবহার করে আপনি সহজেই ডোমেইন অবজেক্ট এবং DTO (Data Transfer Object) এর মধ্যে ডেটা ম্যাপিং করতে পারেন।
এখানে, আমরা দেখব কিভাবে MapStruct এর মাধ্যমে source অবজেক্ট থেকে target অবজেক্টে ডেটা ম্যাপ করা যায়। এই টিউটোরিয়ালে source অবজেক্টকে target অবজেক্টে ম্যাপ করার জন্য একটি সাধারণ উদাহরণ দেওয়া হবে।
১. MapStruct এর মাধ্যমে Mapping করার মূল ধারণা
MapStruct-এ source object থেকে target object তে ডেটা ম্যাপিং একটি Mapper Interface এর মাধ্যমে সম্পন্ন হয়। এই ইন্টারফেসে @Mapper অ্যানোটেশন ব্যবহার করা হয় এবং @Mapping অ্যানোটেশন দিয়ে ম্যাপিং ফিল্ড গুলি কনফিগার করা হয়।
MapStruct মূলত source অবজেক্টের প্রপার্টি গুলোকে target অবজেক্টে ম্যাপ করার জন্য mapping methods ডিফাইন করে, এবং compile-time এ কোড জেনারেট করে।
২. প্রথম MapStruct প্রোগ্রাম: Source এবং Target Object এর Mapping
এখানে আমরা একটি Person ক্লাস এবং তার DTO PersonDTO ক্লাস তৈরি করব এবং MapStruct ব্যবহার করে এই দুটি ক্লাসের মধ্যে ডেটা ম্যাপিং করব।
২.১ Source Object: Person
public class Person {
private String firstName;
private String lastName;
private int age;
// Getters and Setters
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
২.২ Target Object: PersonDTO
public class PersonDTO {
private String fullName;
private int age;
// Getters and Setters
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
এখানে, আমাদের Person এবং PersonDTO ক্লাস তৈরি করা হয়েছে। Person ক্লাসে firstName, lastName এবং age ফিল্ড রয়েছে, আর PersonDTO তে fullName এবং age ফিল্ড রয়েছে।
২.৩ Mapper Interface: PersonMapper
এখন, আমরা একটি Mapper Interface তৈরি করব যা Person থেকে PersonDTO তে ডেটা ম্যাপ করবে।
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
// Mapping method
PersonDTO personToPersonDTO(Person person);
}
এখানে, PersonMapper ইন্টারফেসে একটি personToPersonDTO মেথড তৈরি করা হয়েছে, যা Person অবজেক্ট থেকে PersonDTO অবজেক্টে ডেটা ম্যাপ করবে।
২.৪ Main Class: Mapping ব্যবহার করা
এখন, আমরা Main ক্লাসে ম্যাপিং কার্যক্রম বাস্তবায়ন করব।
public class Main {
public static void main(String[] args) {
// Source object (Person)
Person person = new Person();
person.setFirstName("John");
person.setLastName("Doe");
person.setAge(30);
// Using MapStruct to map Person to PersonDTO
PersonDTO personDTO = PersonMapper.INSTANCE.personToPersonDTO(person);
// Print PersonDTO
System.out.println("Full Name: " + personDTO.getFullName());
System.out.println("Age: " + personDTO.getAge());
}
}
এখানে:
- আমরা একটি Person অবজেক্ট তৈরি করেছি এবং এর ফিল্ডগুলি সেট করেছি।
- MapStruct এর মাধ্যমে Person থেকে PersonDTO তে ডেটা ম্যাপ করার জন্য
PersonMapper.INSTANCE.personToPersonDTO(person)মেথড ব্যবহার করা হয়েছে। - অবশেষে, আমরা PersonDTO এর
fullNameএবংageপ্রিন্ট করেছি।
৩. কাস্টম ম্যাপিং এবং ফিল্ড নাম পরিবর্তন
আপনি যদি চাইছেন যে, firstName এবং lastName এর মান যোগ করে fullName তৈরি করা হোক, তবে কাস্টম ম্যাপিং প্রয়োগ করতে পারেন। MapStruct এ এটি করার জন্য @Mapping অ্যানোটেশন ব্যবহার করা হয়।
৩.১ Custom Mapping Example
@Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
@Mapping(source = "firstName", target = "fullName")
PersonDTO personToPersonDTO(Person person);
}
এখানে, @Mapping অ্যানোটেশনের মাধ্যমে আমরা firstName কে fullName এ ম্যাপ করছি।
৩.২ Full Name Concatenation Example
@Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
@Mapping(target = "fullName", expression = "java(person.getFirstName() + \" \" + person.getLastName())")
PersonDTO personToPersonDTO(Person person);
}
এখানে, expression ব্যবহার করে firstName এবং lastName কে একত্রিত করে fullName তৈরি করা হয়েছে।
৪. Maven Dependency Configuration
MapStruct ব্যবহার করার জন্য, আপনাকে Maven এর pom.xml ফাইলে কিছু নির্দিষ্ট ডিপেনডেন্সি এবং প্লাগইন কনফিগার করতে হবে:
<dependencies>
<!-- MapStruct Dependency -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.2.Final</version>
</dependency>
<!-- MapStruct Processor Dependency (for Code Generation) -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.2.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.2.Final</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
সারাংশ
এই টিউটোরিয়ালে, আমরা MapStruct ব্যবহার করে source object এবং target object এর মধ্যে ডেটা ম্যাপিং করার প্রক্রিয়া শিখেছি। MapStruct এর মাধ্যমে আপনি সহজে ডোমেইন অবজেক্ট এবং DTO এর মধ্যে ডেটা কপি করতে পারেন, যা কোডিংয়ের পরিমাণ কমিয়ে দেয় এবং পারফরম্যান্স উন্নত করে।
এছাড়া, custom mapping এবং field transformations এর মাধ্যমে আরও দক্ষ ডেটা ম্যাপিং করা সম্ভব। MapStruct কোড জেনারেট করার মাধ্যমে টাইপ সেফ এবং দ্রুত ম্যাপিং সম্পন্ন করতে সাহায্য করে।
MapStruct হল একটি শক্তিশালী এবং কার্যকরী টুল যা Source এবং Target অবজেক্টের মধ্যে ডেটা ম্যাপিং সহজ করে তোলে। MapStruct ব্যবহার করে আপনি খুব সহজে JavaBeans বা POJOs এর মধ্যে ডেটা ম্যাপ করতে পারেন। এর মাধ্যমে DTO (Data Transfer Object) এবং Entity ক্লাসের মধ্যে ডেটা ট্রান্সফরমেশন করা খুবই সহজ এবং দ্রুত হয়।
এখানে আমরা MapStruct এর মাধ্যমে Source এবং Target Object এর মধ্যে Mapping করার একটি উদাহরণ দেখব এবং একটি Mapper Interface তৈরি করব।
১. MapStruct এর মাধ্যমে Source এবং Target Object এর Mapping
ধরা যাক, আপনার একটি Source Object (যেমন, Person) এবং একটি Target Object (যেমন, PersonDTO) রয়েছে। MapStruct ব্যবহার করে আপনি Source Object থেকে Target Object এ ডেটা ম্যাপ করতে চান।
১.১ Person (Source Object)
public class Person {
private String firstName;
private String lastName;
private int age;
// Getters and Setters
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
এখানে, Person একটি Source Object যা firstName, lastName, এবং age প্রোপার্টি ধারণ করে।
১.২ PersonDTO (Target Object)
public class PersonDTO {
private String fullName;
private int age;
// Getters and Setters
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
এখানে, PersonDTO একটি Target Object যা fullName এবং age প্রোপার্টি ধারণ করে।
১.৩ PersonMapper (Mapper Interface)
MapStruct এর মাধ্যমে Source Object (Person) থেকে Target Object (PersonDTO) তে ডেটা ম্যাপ করতে, আপনি একটি Mapper Interface তৈরি করবেন। নিচে তার উদাহরণ দেখানো হল:
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
// Mapping method
PersonDTO personToPersonDTO(Person person);
}
এখানে, PersonMapper একটি Mapper Interface যা @Mapper অ্যানোটেশন দ্বারা চিহ্নিত করা হয়েছে। personToPersonDTO মেথডটি Person অবজেক্ট থেকে PersonDTO তে ডেটা ম্যাপ করবে।
১.৪ Mapping Process
এখন, আপনি PersonMapper.INSTANCE.personToPersonDTO(person) মেথড ব্যবহার করে Person থেকে PersonDTO তে ডেটা ট্রান্সফার করতে পারেন। MapStruct এর মাধ্যমে এটি স্বয়ংক্রিয়ভাবে সম্পন্ন হবে।
১.৫ Main Class (Usage Example)
public class Main {
public static void main(String[] args) {
// Creating Person instance
Person person = new Person();
person.setFirstName("John");
person.setLastName("Doe");
person.setAge(30);
// Using MapStruct to map Person to PersonDTO
PersonDTO personDTO = PersonMapper.INSTANCE.personToPersonDTO(person);
// Print PersonDTO
System.out.println("Full Name: " + personDTO.getFullName());
System.out.println("Age: " + personDTO.getAge());
}
}
এখানে, PersonMapper.INSTANCE.personToPersonDTO(person) মেথডটি MapStruct এর মাধ্যমে Person অবজেক্ট থেকে PersonDTO তে ডেটা ম্যাপ করবে। PersonDTO এর fullName ফিল্ডে firstName এবং lastName যোগ করা হবে এবং age একই থাকবে।
২. MapStruct এর মাধ্যমে কাস্টম ম্যাপিং
MapStruct কাস্টম ম্যাপিং সমর্থন করে, যার মাধ্যমে আপনি নিজের লজিক প্রয়োগ করতে পারেন। উদাহরণস্বরূপ, আপনি যদি চান যে Person অবজেক্টের firstName এবং lastName থেকে fullName তৈরি করতে, তবে আপনি MapStruct এর @Mapping অ্যানোটেশন ব্যবহার করতে পারেন।
২.১ Custom Mapping Example
@Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
@Mapping(target = "fullName", expression = "java(person.getFirstName() + \" \" + person.getLastName())")
PersonDTO personToPersonDTO(Person person);
}
এখানে, fullName ফিল্ডটি firstName এবং lastName থেকে কাস্টম expression ব্যবহার করে তৈরি করা হচ্ছে।
৩. MapStruct এর প্রধান সুবিধা
- Compile-time Code Generation: এটি compile-time এ কোড জেনারেট করে, ফলে রানটাইমে কোনো অতিরিক্ত খরচ হয় না, এবং পারফরম্যান্স উন্নত হয়।
- Type Safety: Type-safe ম্যাপিং প্রক্রিয়া, যেখানে runtime ত্রুটি কমে যায় এবং ডেটা ম্যানিপুলেশন সঠিকভাবে হয়।
- No Reflection: MapStruct রিফ্লেকশন ব্যবহার না করায় পারফরম্যান্সে কোনো নেতিবাচক প্রভাব পড়ে না।
- Custom Mappings: কাস্টম ম্যাপিং ফাংশন সহ ম্যাপিংয়ের সুযোগ প্রদান করে।
- Integration with Spring: Spring Framework এর সাথে সহজে ইন্টিগ্রেট করা যায়।
সারাংশ
MapStruct হল একটি শক্তিশালী এবং কার্যকরী টুল যা Source এবং Target Object এর মধ্যে ডেটা মাপিং দ্রুত এবং টাইপ সেফভাবে সম্পন্ন করতে সহায়তা করে। আপনি একটি Mapper Interface তৈরি করে, @Mapper অ্যানোটেশন ব্যবহার করে মডেল ডেটা ট্রান্সফার করতে পারেন। MapStruct কোড জেনারেট করে, যা compile-time এ কাজ করে এবং runtime পারফরম্যান্সে কোনো নেতিবাচক প্রভাব ফেলে না। এর কাস্টম ম্যাপিং, Spring এর সাথে ইন্টিগ্রেশন এবং type safety এর মতো সুবিধাগুলি এটি ব্যবহারের জন্য আরও উপযোগী করে তোলে।
Read more