MapStruct একটি শক্তিশালী Java মডেল ম্যাপিং টুল যা ডোমেইন অবজেক্ট (POJO) থেকে DTO (Data Transfer Object) তে ডেটা ম্যাপিং করে। এক্ষেত্রে, null values এর ব্যবস্থাপনা একটি গুরুত্বপূর্ণ বিষয় হয়ে ওঠে, বিশেষত যখন আপনি ডোমেইন অবজেক্ট থেকে DTO তে বা কোনো ম্যাপিং প্রক্রিয়ায় null ভ্যালু নিয়ে কাজ করেন।
MapStruct সরাসরি null মান পরিচালনার জন্য কিছু বিল্ট-ইন বৈশিষ্ট্য প্রদান করে, এবং প্রয়োজনে আপনি কাস্টম লজিকও প্রয়োগ করতে পারেন।
এই টিউটোরিয়ালে, আমরা MapStruct এর মাধ্যমে null value handling কিভাবে কাজ করে তা আলোচনা করব এবং উদাহরণ দেখাবো।
১. MapStruct এর মাধ্যমে Null Handling
MapStruct ডিফল্টভাবে, যখন কোনও source অবজেক্টের ফিল্ড null থাকে, তখন লক্ষ্য (target) অবজেক্টে ওই ফিল্ডের মানও null সেট করবে। তবে, যদি আপনি null মানের জন্য কাস্টম লজিক প্রয়োগ করতে চান, তখন MapStruct এর কিছু কনফিগারেশন প্যারামিটার ব্যবহার করে এটি করতে পারবেন।
Null Handling Default Behavior:
ডিফল্টভাবে, MapStruct null values এর জন্য কোনো বিশেষ কাস্টম রূপান্তর বা লজিক প্রয়োগ করে না, তবে source অবজেক্টে যদি কোনো প্রপার্টি null থাকে, তবে target অবজেক্টে সেই প্রপার্টি null থাকবে।
২. MapStruct এ Null Handling কনফিগারেশন
MapStruct বিভিন্ন পদ্ধতিতে null values এর সাথে কাজ করতে সহায়তা করে, যেমন:
- Null Value Mapping: আপনি যদি চান যে যখন কোনো মান
nullথাকে, তখন এটি একটি ডিফল্ট মানে সেট হয়ে যায় (যেমন, একটিStringকে""দিয়ে প্রতিস্থাপন করা)। - Null Check: আপনি যদি চান যে যদি কোনো ভ্যালু
nullথাকে, তবে ম্যাপিংয়ের পরিবর্তে কিছু নির্দিষ্ট ক্রিয়া সম্পন্ন করা হোক, যেমন ফালস রিটার্ন করা।
উদাহরণ ১: Default Null Value Handling
যদি Person ক্লাসের name ফিল্ডের মান null হয়, তবে PersonDTO তে ওই ফিল্ডের মানও null থাকবে।
public class Person {
private String name;
private int age;
// Getters and Setters
}
public class PersonDTO {
private String name;
private int age;
// Getters and Setters
}
PersonMapper.java:
@Mapper
public interface PersonMapper {
PersonDTO personToPersonDTO(Person person);
}
এখানে, যদি Person এর name ফিল্ড null থাকে, তবে PersonDTO এর name ফিল্ডও null হবে।
৩. Null Value Handling কাস্টমাইজ করা
MapStruct আপনাকে কাস্টম null handling এর জন্য @Mapping অ্যানোটেশন ব্যবহার করে কাস্টম রূপান্তর প্রয়োগ করতে দেয়। আপনি @Mapping এর মাধ্যমে কাস্টম null মান সেট করতে পারেন।
উদাহরণ ২: Null Value এর জন্য Default Value সেট করা
ধরা যাক, যদি name ফিল্ডের মান null থাকে, তাহলে আপনি সেটি "Unknown" হিসেবে সেট করতে চান।
@Mapper
public interface PersonMapper {
@Mapping(target = "name", defaultValue = "Unknown")
PersonDTO personToPersonDTO(Person person);
}
এখানে, যদি Person অবজেক্টের name ফিল্ডের মান null থাকে, তাহলে PersonDTO তে name ফিল্ড "Unknown" হবে।
৪. Custom Null Value Mapping Using Expression
আপনি যদি চাইলে expression ব্যবহার করে কাস্টম null হ্যান্ডলিং লজিক প্রয়োগ করতে পারেন। এতে আপনি কাস্টম কনভার্টার ফাংশন বা লজিক যোগ করতে পারেন।
উদাহরণ ৩: Expression ব্যবহার করে Null Mapping
@Mapper
public interface PersonMapper {
@Mapping(target = "name", expression = "java(person.getName() == null ? \"Unknown\" : person.getName())")
PersonDTO personToPersonDTO(Person person);
}
এখানে, expression ব্যবহার করে যখন person.getName() null হবে, তখন "Unknown" সেট হবে, আর না হলে মূল name মানটি থাকবে।
৫. Null Value Handling এবং Collection Mapping
MapStruct এ Collection বা Array এর ক্ষেত্রে যখন কোনো একক ভ্যালু null হয়, তখন Collection বা Array তেও null ভ্যালু অ্যাড করা হতে পারে, তবে MapStruct এ আপনি কাস্টম null value হ্যান্ডলিং করতে পারেন।
উদাহরণ ৪: Collection Null Handling
ধরা যাক, Person অবজেক্টের একটি List আছে, যেখানে যদি কোনো অবজেক্ট null হয়, তাহলে আপনি সেটি বাদ দিতে চান।
@Mapper
public interface PersonMapper {
@Mapping(target = "people", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
PersonDTO personToPersonDTO(Person person);
}
এখানে, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE ব্যবহার করে List বা Collection থেকে null আইটেমগুলো উপেক্ষা করা হবে।
৬. Null Value Handling for Nested Object Mapping
MapStruct আপনাকে nested objects এর জন্যও null মান হ্যান্ডলিং কাস্টমাইজ করার সুযোগ দেয়। ধরুন, আপনি যখন Parent-Child Object Mapping করছেন, তখন Child অবজেক্টের null মানের জন্য আপনি কাস্টম লজিক প্রয়োগ করতে পারেন।
উদাহরণ ৫: Nested Object Mapping এবং Null Handling
public class Address {
private String city;
// Getters and Setters
}
public class Person {
private String name;
private Address address;
// Getters and Setters
}
public class PersonDTO {
private String name;
private String city;
// Getters and Setters
}
@Mapper
public interface PersonMapper {
@Mapping(source = "address.city", target = "city", defaultValue = "Unknown")
PersonDTO personToPersonDTO(Person person);
}
এখানে, যদি Person এর address ফিল্ড null থাকে, তবে PersonDTO এর city ফিল্ড "Unknown" হয়ে যাবে।
৭. MapStruct এর সাথে Null Value Handling কনফিগারেশন
MapStruct আপনাকে NullValuePropertyMappingStrategy ব্যবহার করার সুযোগ দেয়, যা আপনি @Mapping অ্যানোটেশনের মাধ্যমে নির্ধারণ করতে পারেন।
- NullValuePropertyMappingStrategy.SET_TO_DEFAULT: এটি null মানকে ডিফল্ট মানে পরিবর্তন করবে।
- NullValuePropertyMappingStrategy.IGNORE: এটি null মানকে উপেক্ষা করবে এবং ম্যাপিংয়ে কোনো পরিবর্তন করবে না।
উদাহরণ ৬: Null Value Property Mapping Strategy
@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
public interface PersonMapper {
PersonDTO personToPersonDTO(Person person);
}
এখানে, SET_TO_DEFAULT কনফিগারেশন ব্যবহার করা হয়েছে, যার মানে null ফিল্ডগুলি ডিফল্ট মানে (যেমন "" বা 0 ইত্যাদি) সেট হবে।
সারাংশ
MapStruct ব্যবহার করে null value handling খুবই সহজ। আপনি defaultValue সেট করতে পারেন, expression ব্যবহার করে কাস্টম লজিক প্রয়োগ করতে পারেন অথবা NullValuePropertyMappingStrategy ব্যবহার করে null মানের জন্য নির্দিষ্ট কৌশল প্রয়োগ করতে পারেন। MapStruct এর মাধ্যমে null ভ্যালু গুলি সরাসরি default মানে সেট করা, উপেক্ষা করা বা কাস্টম মান সেট করার মতো কার্যকারিতা সহজেই সম্পাদিত হয়, যা পারফরম্যান্সে কোনো নেতিবাচক প্রভাব ফেলে না এবং কোডকে আরও সুসংগঠিত রাখে।
MapStruct একটি শক্তিশালী টুল যা JavaBeans (POJOs) এর মধ্যে ম্যাপিং সহজ করে তোলে। তবে, যখন কোনো ভ্যালু null থাকে, তখন ম্যাপিংয়ের সময় কিছু সমস্যা সৃষ্টি হতে পারে, বিশেষত যদি এটি কোনো প্রপার্টির মান হয় এবং আপনার ডোমেইন অবজেক্টে সেট করা না থাকে। MapStruct এর মধ্যে null values এর সমস্যা সমাধান করার জন্য কিছু নির্দিষ্ট কৌশল রয়েছে, যা আপনার ম্যাপিং প্রক্রিয়াকে আরো স্থিতিশীল এবং নির্ভুল করে তোলে।
এই টিউটোরিয়ালে আমরা আলোচনা করব MapStruct এর মাধ্যমে null values এর সমস্যা এবং এর সমাধান পদ্ধতি।
১. MapStruct এবং Null Values
ম্যাপস্ট্রাক্ট null values এর ক্ষেত্রে কীভাবে কাজ করবে তা ডিফল্টভাবে নির্ধারণ করা থাকে। সাধারণত, null ভ্যালু গুলি সরাসরি ডেস্টিনেশন অবজেক্টে প্রেরিত হয়। তবে কিছু পরিস্থিতিতে আপনি চাচ্ছেন না যে null ভ্যালু সরাসরি ডেস্টিনেশন অবজেক্টে পৌঁছাক। এর জন্য MapStruct কিছু কাস্টম কনফিগারেশন এবং অপশন সরবরাহ করে।
Default Behavior:
MapStruct সাধারণত একটি null ভ্যালু শর্তসাপেক্ষভাবে মেনে নেয় এবং গন্তব্য অবজেক্টে সেই null ভ্যালু সেট করে। তবে, এটি কিছুক্ষেত্রে অপ্রত্যাশিত ফলাফল প্রদান করতে পারে, যেমন null pointer exceptions বা incorrect mappings।
২. Null Value Handling with @Mapping Annotation
MapStruct আপনাকে @Mapping অ্যানোটেশনের মাধ্যমে null ভ্যালু হ্যান্ডেল করার কিছু কৌশল প্রদান করে। আপনি যদি চান যে null ভ্যালু গুলি কিভাবে ম্যাপিং হবে তা নিয়ন্ত্রণ করতে, তাহলে nullValueCheckStrategy বা defaultValue ব্যবহার করতে পারেন।
২.১ nullValueCheckStrategy এর ব্যবহার
MapStruct nullValueCheckStrategy ব্যবহার করে null values এর ক্ষেত্রে কাস্টম চেকিং করতে সাহায্য করে। এটি আপনাকে নির্দিষ্ট করতে দেয়, যদি সোর্স অবজেক্টের কোনো ভ্যালু null হয়, তাহলে কী করতে হবে।
উদাহরণ: nullValueCheckStrategy ব্যবহার
@Mapper
public interface PersonMapper {
@Mapping(source = "firstName", target = "fullName", nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
PersonDTO personToPersonDTO(Person person);
}
এখানে, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS দ্বারা null ভ্যালু চেক করা হয় এবং সেটির জন্য নির্দিষ্ট প্রক্রিয়া গ্রহণ করা হয়। আপনি ALWAYS বা ON_IMPLICIT_CONVERSION চয়ন করতে পারেন।
NullValueCheckStrategy Options:
- ALWAYS: সোর্স অবজেক্টে null থাকলে, ডেস্টিনেশন অবজেক্টে null পাঠানো হবে।
- ON_IMPLICIT_CONVERSION: শুধুমাত্র সেই ক্ষেত্রগুলোতে null চেক করবে যেখানে null কনভার্শন সম্ভব।
- NEVER: null চেক হবে না এবং যেকোনো null ভ্যালু কপি করা হবে।
৩. defaultValue অপশন ব্যবহার
MapStruct আপনাকে defaultValue সেট করার অপশন দেয়, যেখানে আপনি null ভ্যালুর জন্য একটি ডিফল্ট ভ্যালু নির্ধারণ করতে পারেন।
৩.১ defaultValue অপশন ব্যবহার
@Mapper
public interface PersonMapper {
@Mapping(source = "firstName", target = "fullName", defaultValue = "Unknown")
PersonDTO personToPersonDTO(Person person);
}
এখানে, যদি firstName null থাকে, তাহলে ডিফল্ট ভ্যালু হিসেবে "Unknown" সেট করা হবে।
৪. Null Handling Using @MappingTarget
MapStruct @MappingTarget এর মাধ্যমে কিছু ক্ষেত্রে null values সেট করতে ব্যবহৃত হয়। এটি বিশেষত তখন দরকার হয় যখন আপনি একটি প্রাপ্ত অবজেক্টে নতুন ডেটা ম্যাপ করতে চান এবং আগের null ভ্যালু রক্ষা করতে চান।
৪.১ @MappingTarget এর ব্যবহার
@Mapper
public interface PersonMapper {
@Mapping(target = "fullName", source = "firstName")
void updatePersonFromDto(PersonDTO dto, @MappingTarget Person person);
}
এখানে, যদি firstName null হয়, তাহলে fullName এ আগের মান রেখে দেওয়ার জন্য এই কৌশল ব্যবহৃত হবে।
৫. @BeforeMapping এবং @AfterMapping Methods
MapStruct আপনাকে @BeforeMapping এবং @AfterMapping অ্যানোটেশন দিয়ে একটি null check প্রক্রিয়া সম্পাদন করতে সহায়তা করে। আপনি এই মেথডগুলিতে null ভ্যালু চেক করে নিজস্ব লজিক প্রয়োগ করতে পারেন।
৫.১ @BeforeMapping এবং @AfterMapping এর ব্যবহার
@Mapper
public interface PersonMapper {
@BeforeMapping
default void handleNullValues(Person person) {
if (person.getFirstName() == null) {
person.setFirstName("Default Name");
}
}
PersonDTO personToPersonDTO(Person person);
}
এখানে, @BeforeMapping মেথডে null চেক করা হচ্ছে এবং প্রয়োজন হলে ডিফল্ট ভ্যালু সেট করা হচ্ছে।
৬. MapStruct এবং Spring Integration এর সাথে Null Handling
MapStruct এর null handling Spring-এর Optional টাইপ বা @Value অ্যানোটেশনের সাথে ইন্টিগ্রেট করা যেতে পারে। Spring কনটেক্সটে Optional ব্যবহার করে null safety আরও উন্নত করা সম্ভব।
উদাহরণ: Optional এর মাধ্যমে Null Handling
@Mapper(componentModel = "spring")
public interface PersonMapper {
@Mapping(source = "firstName", target = "fullName", defaultValue = "Default Name")
PersonDTO personToPersonDTO(Person person);
}
এখানে, Spring ইন্টিগ্রেশন ব্যবহার করে MapStruct কাস্টম ম্যাপিং সাপোর্ট করা হয়েছে।
৭. Null Handling Tips
- Null Safety: MapStruct আপনাকে null ভ্যালু সঠিকভাবে হ্যান্ডেল করতে সহায়তা করে, তবে কখনও কখনও ডিফল্ট ভ্যালু বা কাস্টম ম্যাপিং ফাংশন ব্যবহার করা প্রয়োজন।
- Consistency: null চেক করার নিয়মটি প্রোজেক্টের সমস্ত কোডে কনসিস্টেন্ট রাখুন যাতে মানসম্পন্ন ম্যাপিং হয়।
- Use Optional for Optional Fields: যদি আপনার ফিল্ডটি Optional হয়, তবে সেটি সঠিকভাবে ম্যানেজ করুন।
- Avoid NullPointerException: null ভ্যালু ইনপুট ফিল্ডের জন্য ডিফল্ট ভ্যালু ব্যবহার করতে পারেন যাতে কোডে ত্রুটি কমে যায়।
সারাংশ
MapStruct এর মাধ্যমে null values হ্যান্ডেল করা খুবই গুরুত্বপূর্ণ, বিশেষত যখন আপনি ডেটা ট্রান্সফার অবজেক্ট (DTO) এবং ডোমেইন অবজেক্টের মধ্যে ম্যাপিং করছেন। nullValueCheckStrategy, defaultValue, @MappingTarget এবং @BeforeMapping সহ বিভিন্ন কৌশল ব্যবহার করে আপনি null ভ্যালু হ্যান্ডেল করতে পারেন এবং আপনার প্রোজেক্টের পারফরম্যান্স এবং স্থিতিশীলতা উন্নত করতে পারেন। MapStruct আপনাকে null values এর উপর পূর্ণ নিয়ন্ত্রণ দেয়, যাতে ম্যাপিং প্রক্রিয়া আরও নির্ভরযোগ্য এবং কার্যকরী হয়।
MapStruct একটি শক্তিশালী model mapping টুল যা JavaBeans বা POJOs এর মধ্যে ডেটা ম্যাপিং করতে ব্যবহৃত হয়। এটি অটোমেটিক কোড জেনারেশন করে, যা দ্রুত এবং কার্যকরী ডেটা ট্রান্সফার সরবরাহ করে। তবে, null values এর ক্ষেত্রে সঠিক হ্যান্ডলিং অত্যন্ত গুরুত্বপূর্ণ, কারণ null ম্যাপিংয়ের কারণে NullPointerException বা ভুল মান ট্রান্সফারের মতো সমস্যা হতে পারে।
এই টিউটোরিয়ালে, আমরা দেখব MapStruct এ কিভাবে null values সঠিকভাবে হ্যান্ডেল করা যায় এবং কিছু কৌশল ও টিপস শেয়ার করব যা null values এর প্রভাব কমাবে।
১. MapStruct এ Default Null Handling
MapStruct স্বাভাবিকভাবে null values হ্যান্ডেল করার জন্য কিছু ডিফল্ট নিয়ম অনুসরণ করে। উদাহরণস্বরূপ, যদি ম্যাপিং করার সময় কোনো ফিল্ডের মান null থাকে, তবে সেটি null হিসেবেই রিটার্ন করবে।
উদাহরণ:
public class Employee {
private String name;
private Integer age;
// Getters and Setters
}
public class EmployeeDTO {
private String name;
private Integer age;
// Getters and Setters
}
@Mapper
public interface EmployeeMapper {
EmployeeDTO employeeToEmployeeDTO(Employee employee);
}
এখানে, যদি Employee অবজেক্টের name বা age ফিল্ড null থাকে, তবে EmployeeDTO এর সমান ফিল্ডও null হয়ে যাবে। এই ডিফল্ট null হ্যান্ডলিং খুবই সাধারণ এবং অনেক সময় প্রয়োজনীয় হয়।
২. MapStruct এ Null Handling কাস্টমাইজ করা
MapStruct আপনাকে null values হ্যান্ডলিং কাস্টমাইজ করার সুযোগ দেয়, যাতে আপনি বিশেষ পরিস্থিতিতে null মানের জন্য আলাদা আচরণ নির্ধারণ করতে পারেন। এর জন্য MapStruct @Mapping অ্যানোটেশন ব্যবহার করে কাস্টম nullValueCheckStrategy এবং nullValuePropertyMappingStrategy প্যারামিটার সরবরাহ করে।
২.১ nullValueCheckStrategy
এটি null মান পরীক্ষা করার কৌশল নির্ধারণ করে। সাধারণত, যদি কোনো ফিল্ড null হয়, তবে সেটা null হিসেবে ম্যাপ হবে। কিন্তু আপনি চাইলে null ফিল্ডের জন্য default মান দিতে পারেন।
উদাহরণ: nullValueCheckStrategy
@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
public interface EmployeeMapper {
@Mapping(target = "name", source = "name", nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
EmployeeDTO employeeToEmployeeDTO(Employee employee);
}
এখানে, ALWAYS ব্যবহার করা হয়েছে, যা মানে হল যে সব ক্ষেত্রেই null value চেক হবে এবং সেগুলিকে null হিসেবে সেট করা হবে।
২.২ nullValuePropertyMappingStrategy
এই প্যারামিটারটি যখন null মান হয়, তখন ম্যাপিংয়ের কিভাবে হ্যান্ডল করা হবে তা নির্ধারণ করে। আপনি এটি ব্যবহার করে null মানের জন্য default মান নির্ধারণ করতে পারেন, অথবা আপনি চাইলে null মানের ক্ষেত্রে কোনো ফিল্ড মান না সেট করার সিদ্ধান্ত নিতে পারেন।
উদাহরণ: nullValuePropertyMappingStrategy
@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public interface EmployeeMapper {
@Mapping(target = "name", source = "name")
EmployeeDTO employeeToEmployeeDTO(Employee employee);
}
এখানে, IGNORE ব্যবহার করা হয়েছে, যা মানে হল যে যদি কোনো প্রপার্টি null থাকে, তবে সেই প্রপার্টি ম্যাপিংয়ে অন্তর্ভুক্ত হবে না।
৩. Null Handling for Nested Objects
কখনও কখনও null values নেস্টেড অবজেক্টের মধ্যে থাকে এবং সেগুলোর সঠিক হ্যান্ডলিং অত্যন্ত গুরুত্বপূর্ণ। MapStruct এর মাধ্যমে আপনি নেস্টেড অবজেক্টগুলির null মান সঠিকভাবে হ্যান্ডেল করতে পারেন।
উদাহরণ: Nested Object Mapping with Null Handling
public class Department {
private String departmentName;
// Getters and Setters
}
public class Employee {
private String name;
private Department department;
// Getters and Setters
}
public class EmployeeDTO {
private String name;
private String departmentName;
// Getters and Setters
}
@Mapper
public interface EmployeeMapper {
@Mapping(source = "department.departmentName", target = "departmentName")
EmployeeDTO employeeToEmployeeDTO(Employee employee);
}
এখানে, যদি Employee অবজেক্টের department ফিল্ড null হয়, তবে MapStruct departmentName ফিল্ডে null মান সেট করবে, যদি না nullValuePropertyMappingStrategy দিয়ে অন্য কোনো কৌশল নির্ধারণ করা হয়।
৪. Null Value Handling with Custom Methods
আপনি যদি null মানের জন্য কাস্টম হ্যান্ডলিং চাইলে, তখন আপনাকে custom methods ব্যবহার করতে হবে, যা null চেক করার পরে নির্দিষ্ট মান প্রদান করবে।
উদাহরণ: Custom Method for Null Handling
public class Employee {
private String name;
private Integer age;
// Getters and Setters
}
public class EmployeeDTO {
private String name;
private Integer age;
// Getters and Setters
}
@Mapper
public interface EmployeeMapper {
@Mapping(target = "age", expression = "java(getDefaultAge(employee))")
EmployeeDTO employeeToEmployeeDTO(Employee employee);
default Integer getDefaultAge(Employee employee) {
return (employee.getAge() == null) ? 18 : employee.getAge(); // Return default value if age is null
}
}
এখানে, getDefaultAge মেথডটি ব্যবহার করা হয়েছে, যা null age থাকলে 18 ফিরিয়ে দেবে।
৫. MapStruct এবং NullPointerException
MapStruct এর null value হ্যান্ডলিং কোড জেনারেট করে এবং এতে NullPointerException হওয়া এড়ানো হয়। যদি আপনি কোনো null মানের সাথে কাজ করেন, তবে MapStruct null চেক করে সেই ভ্যালু null হিসেবে ম্যাপ করবে। তবে, যদি আপনি null এর জন্য বিশেষ কাস্টম লজিক চান, তবে উপরের মতো কাস্টম মেথড ব্যবহার করতে পারেন।
সারাংশ
MapStruct এ null values সঠিকভাবে হ্যান্ডেল করা খুবই গুরুত্বপূর্ণ, যাতে ডেটা ট্রান্সফারের সময় কোনো ত্রুটি বা সমস্যা না হয়। MapStruct এর nullValueCheckStrategy এবং nullValuePropertyMappingStrategy প্যারামিটার ব্যবহার করে আপনি null মানের জন্য কাস্টম হ্যান্ডলিং নির্ধারণ করতে পারেন। এছাড়া, custom methods ব্যবহার করে আপনি আরো উন্নত null হ্যান্ডলিং যুক্ত করতে পারেন, যা আপনার প্রোজেক্টের জন্য কার্যকর হতে পারে।
MapStruct একটি Java annotation processor ভিত্তিক লাইব্রেরি যা অবজেক্ট ম্যাপিং এর জন্য অটোমেটিক কোড জেনারেট করে। যখন আপনি দুটি অবজেক্টের মধ্যে ডেটা ম্যাপিং করেন, তখন কিছু ক্ষেত্রে আপনি চান যে, যদি সোর্স অবজেক্টে কোন ফিল্ডের মান null হয়, তবে তা টার্গেট অবজেক্টে কিভাবে হ্যান্ডল হবে, সেই কনফিগারেশন করতে। MapStruct এই সমস্যা সমাধান করতে @Mapping অ্যানোটেশনের nullValueMappingStrategy অ্যাট্রিবিউট প্রদান করে।
এই অ্যাট্রিবিউটটি ব্যবহার করার মাধ্যমে আপনি নির্দিষ্ট করতে পারবেন যে, যখন সোর্স অবজেক্টের কোন ফিল্ড null থাকে, তখন সেই ফিল্ডের মান টার্গেট অবজেক্টে কী হবে। আপনি এটিকে বিভিন্ন স্ট্র্যাটেজি অনুসারে কনফিগার করতে পারেন।
১. nullValueMappingStrategy অ্যাট্রিবিউট এর মূল উদ্দেশ্য
nullValueMappingStrategy অ্যাট্রিবিউট মূলত দুটি ফিল্ডের মধ্যে null মান ম্যানেজ করার জন্য ব্যবহৃত হয়। এই অ্যাট্রিবিউটটি @Mapping অ্যানোটেশনে যোগ করা হয় এবং এটি নির্ধারণ করে যে null মান কি হ্যান্ডেল করা হবে:
- SET_TO_NULL: যদি সোর্স ফিল্ড null হয়, তবে টার্গেট ফিল্ডে null সেট করা হবে।
- IGNORE: যদি সোর্স ফিল্ড null হয়, তবে টার্গেট ফিল্ডের কোন পরিবর্তন হবে না।
- SET_DEFAULT: যদি সোর্স ফিল্ড null হয়, তবে ডিফল্ট মান (যেমন, 0, "" ইত্যাদি) সেট হবে।
২. @Mapping এর nullValueMappingStrategy অ্যাট্রিবিউট ব্যবহার করার উদাহরণ
এখন, আমরা nullValueMappingStrategy অ্যাট্রিবিউট ব্যবহার করার কিছু উদাহরণ দেখবো।
উদাহরণ ১: SET_TO_NULL স্ট্র্যাটেজি
ধরা যাক, আমাদের দুটি ক্লাস Person এবং PersonDTO আছে, এবং আমরা চাই যে, যদি Person ক্লাসের address ফিল্ড null হয়, তবে PersonDTO তে null সেট করা হোক।
Person.java:
public class Person {
private String name;
private String address;
// Getters and Setters
}
PersonDTO.java:
public class PersonDTO {
private String name;
private String address;
// Getters and Setters
}
PersonMapper.java:
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface PersonMapper {
@Mapping(source = "address", target = "address", nullValueMappingStrategy = NullValueMappingStrategy.SET_TO_NULL)
PersonDTO personToPersonDTO(Person person);
}
এখানে, যদি address ফিল্ড null থাকে, তবে PersonDTO এর address ফিল্ডে null সেট করা হবে।
উদাহরণ ২: IGNORE স্ট্র্যাটেজি
ধরা যাক, আমরা চাই যে, যদি Person ক্লাসের address ফিল্ড null হয়, তবে PersonDTO তে কোনো পরিবর্তন না ঘটে।
PersonMapper.java:
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface PersonMapper {
@Mapping(source = "address", target = "address", nullValueMappingStrategy = NullValueMappingStrategy.IGNORE)
PersonDTO personToPersonDTO(Person person);
}
এখানে, address ফিল্ডের মান যদি null হয়, তাহলে PersonDTO এর address ফিল্ডে কোন পরিবর্তন হবে না এবং আগের মান থেকে যাবে।
উদাহরণ ৩: SET_DEFAULT স্ট্র্যাটেজি
ধরা যাক, আপনি চাইছেন যে, যদি সোর্স অবজেক্টের কোন ফিল্ড null হয়, তাহলে টার্গেট অবজেক্টের ওই ফিল্ডে ডিফল্ট মান (যেমন, খালি স্ট্রিং বা 0) সেট করা হবে।
PersonMapper.java:
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface PersonMapper {
@Mapping(source = "address", target = "address", nullValueMappingStrategy = NullValueMappingStrategy.SET_DEFAULT)
PersonDTO personToPersonDTO(Person person);
}
এখানে, যদি address ফিল্ড null হয়, তাহলে এটি টার্গেট অবজেক্টে ডিফল্ট মান (যেমন, "Default Address") সেট করবে।
৩. MapStruct এর nullValueMappingStrategy এর প্রয়োগ
এখন, প্রতিটি স্ট্র্যাটেজি এবং তার প্রয়োগ দেখে নিন:
- SET_TO_NULL: সোর্সের null মান টার্গেটের null মানে পরিণত হয়।
- IGNORE: সোর্সের null মান টার্গেট ফিল্ডে কোনো পরিবর্তন ঘটায় না।
- SET_DEFAULT: সোর্সের null মানে টার্গেট ফিল্ডে একটি ডিফল্ট মান সেট হয়।
এই স্ট্র্যাটেজিগুলি ব্যবহারের মাধ্যমে আপনি ডেটা ট্রান্সফার বা ম্যাপিংয়ে নির্দিষ্ট আচরণ নিয়ন্ত্রণ করতে পারেন এবং null মানের ক্ষেত্রে যথাযথ ফলাফল অর্জন করতে পারেন।
৪. nullValueMappingStrategy কিভাবে নির্বাচিত করবেন?
- যদি আপনি চান যে সোর্স ফিল্ড null হলে টার্গেট ফিল্ডে null সেট করা হোক, তবে SET_TO_NULL ব্যবহার করুন।
- যদি আপনি চান যে সোর্স ফিল্ড null হলে টার্গেট ফিল্ডে কোনো পরিবর্তন না ঘটে, তবে IGNORE ব্যবহার করুন।
- যদি আপনি চান যে সোর্স ফিল্ড null হলে টার্গেট ফিল্ডে একটি ডিফল্ট মান সেট করা হোক, তবে SET_DEFAULT ব্যবহার করুন।
এভাবে, nullValueMappingStrategy এর মাধ্যমে null মানের হ্যান্ডলিং এবং ম্যাপিং কার্যক্রম কাস্টমাইজ করা সম্ভব।
সারাংশ
@Mapping এর nullValueMappingStrategy অ্যাট্রিবিউট MapStruct এর একটি শক্তিশালী ফিচার যা null মানের হ্যান্ডলিং নিয়ন্ত্রণ করতে সাহায্য করে। SET_TO_NULL, IGNORE, এবং SET_DEFAULT স্ট্র্যাটেজির মাধ্যমে আপনি নির্দিষ্ট করতে পারেন যে সোর্স অবজেক্টের null ফিল্ডের মান টার্গেট অবজেক্টে কী হবে। এটি ম্যাপিং প্রক্রিয়াকে আরও নমনীয় এবং কাস্টমাইজড করে তোলে, বিশেষত যখন null মানের প্রভাব ম্যানেজ করা প্রয়োজন।
MapStruct একটি শক্তিশালী Java মডেল ম্যাপিং টুল যা বিভিন্ন ধরনের অবজেক্টের মধ্যে ডেটা ম্যাপিং করে। তবে, যখন আপনি null ভ্যালু ম্যাপ করেন, তখন কিছু বিশেষ কনফিগারেশন প্রয়োজন হয়, যেমন null handling বা null-safe mapping। MapStruct আপনাকে বিভিন্ন পদ্ধতিতে null ভ্যালু পরিচালনা করতে সহায়তা করে, যাতে null pointer exceptions বা অপ্রত্যাশিত ফলাফল এড়ানো যায়।
এই টিউটোরিয়ালে, আমরা MapStruct ব্যবহার করে null value handling কিভাবে করা যায় তা উদাহরণসহ আলোচনা করব।
১. Null Value Handling in MapStruct
MapStruct ডিফল্টভাবে null values অটোমেটিক্যালি পাশ করে দেয় এবং যদি আপনি কোনো null ভ্যালু পেয়েছেন, তবে কোনো ম্যাপিং করা হবে না। তবে কখনো কখনো আপনি চাইবেন যে, null values এর ক্ষেত্রে কিছু কাস্টম লজিক প্রয়োগ করতে।
MapStruct এ null ভ্যালু ব্যবহারের জন্য নিচের কিছু পদ্ধতি রয়েছে:
- Default Behavior:
nullভ্যালু সরাসরি প্রসেস না করলেই, null টার্গেট ফিল্ডে চলে যায়। - @Mapping annotation: আপনি
@Mappingঅ্যানোটেশন ব্যবহার করে null ভ্যালু হ্যান্ডেল করতে পারবেন। - @Mapping with defaultValue: আপনি defaultValue নির্ধারণ করতে পারেন, যাতে null পাওয়ার ক্ষেত্রে একটি ডিফল্ট মান নির্ধারণ করা হয়।
২. Default Null Handling (ডিফল্ট Null হ্যান্ডলিং)
MapStruct সাধারণত, যদি আপনি কোনো null ভ্যালু ইনপুট হিসেবে পেয়ে থাকেন, তবে তা সরাসরি টার্গেট প্রপার্টিতে সেট করে দেয়। যেমন:
উদাহরণ:
public class Person {
private String name;
private Integer age;
// Getters and Setters
}
public class PersonDTO {
private String name;
private Integer age;
// Getters and Setters
}
@Mapper
public interface PersonMapper {
PersonDTO personToPersonDTO(Person person);
}
এখানে, যদি Person অবজেক্টের name বা age ফিল্ডের কোনো মান null হয়, তবে PersonDTO তে সেই ফিল্ডেও null সেট হবে।
৩. @Mapping Annotation ব্যবহার করে Null Value Handling
MapStruct এ আপনি @Mapping অ্যানোটেশন ব্যবহার করে null ভ্যালু হ্যান্ডেল করতে পারেন। এর মাধ্যমে আপনি null ভ্যালু পাওয়ার ক্ষেত্রে একটি ডিফল্ট মান নির্ধারণ করতে পারেন।
উদাহরণ: Default Value for Null
@Mapper
public interface PersonMapper {
@Mapping(source = "name", target = "name", defaultValue = "Unknown")
@Mapping(source = "age", target = "age", defaultValue = "0")
PersonDTO personToPersonDTO(Person person);
}
এখানে, যদি name বা age ফিল্ডে null ভ্যালু থাকে, তাহলে defaultValue এর মাধ্যমে ডিফল্ট মান নির্ধারণ করা হবে। এর মানে:
- যদি name এর মান
nullহয়, তাহলে "Unknown" সেট হবে। - যদি age এর মান
nullহয়, তাহলে 0 সেট হবে।
৪. Null Check Method (Null চেক মেথড)
ম্যাপিংয়ের জন্য কাস্টম null check মেথড ব্যবহার করা যেতে পারে। MapStruct আপনাকে @BeforeMapping অ্যানোটেশন ব্যবহার করে কাস্টম ম্যাপিং ফাংশন তৈরি করার সুযোগ দেয়, যা null চেক করার জন্য ব্যবহার করা যেতে পারে।
উদাহরণ: Custom Null Check
@Mapper
public interface PersonMapper {
@Mapping(source = "name", target = "name")
@Mapping(source = "age", target = "age")
PersonDTO personToPersonDTO(Person person);
default String mapName(String name) {
return name != null ? name : "Default Name";
}
default Integer mapAge(Integer age) {
return age != null ? age : 18;
}
}
এখানে, mapName() এবং mapAge() মেথডগুলো null চেক করছে এবং যদি null থাকে, তবে ডিফল্ট মান সরবরাহ করছে।
৫. @Mapping with QualifiedByName
MapStruct আপনাকে কাস্টম ম্যাপিং লজিক ব্যবহার করতে সাহায্য করে যখন আপনি নির্দিষ্ট null ভ্যালুর জন্য নির্দিষ্ট মান চান। এটি qualifiedByName বা qualifiedBy অ্যানোটেশন ব্যবহার করে করা যেতে পারে।
উদাহরণ: Custom Mapping with QualifiedByName
@Mapper
public interface PersonMapper {
@Mapping(source = "name", target = "name", qualifiedByName = "mapName")
PersonDTO personToPersonDTO(Person person);
@Named("mapName")
default String mapName(String name) {
return name != null ? name : "Custom Default Name";
}
}
এখানে, @Named অ্যানোটেশন ব্যবহার করে কাস্টম ম্যাপিং মেথড mapName() তৈরি করা হয়েছে, যা null নামের জন্য একটি কাস্টম ডিফল্ট মান প্রদান করবে।
৬. Null Handling for Nested Objects (নেস্টেড অবজেক্টে Null Handling)
MapStruct এর মাধ্যমে আপনি nested objects এর মধ্যে null handling করতে পারেন। যদি কোনো নেস্টেড অবজেক্ট null হয়, তাহলে MapStruct ডিফল্টভাবে null মান সেট করবে।
উদাহরণ: Null Handling in Nested Objects
public class Address {
private String street;
private String city;
// Getters and Setters
}
public class Person {
private String name;
private Address address;
// Getters and Setters
}
public class PersonDTO {
private String name;
private String street;
private String city;
// Getters and Setters
}
@Mapper
public interface PersonMapper {
@Mapping(source = "address.street", target = "street")
@Mapping(source = "address.city", target = "city")
PersonDTO personToPersonDTO(Person person);
}
এখানে, যদি Address অবজেক্ট null হয়, তাহলে street এবং city ফিল্ডে null মান চলে যাবে।
৭. Null Value Handling with Collection Mapping
যখন আপনার Collection বা Array ম্যাপিং থাকে, তখনও null ভ্যালু হ্যান্ডলিং করতে পারেন। MapStruct null ভ্যালু গুলি উপেক্ষা করে এবং যখন কোনো এলিমেন্ট null হয়, তখন সেই এলিমেন্টটিকে null হিসেবে রাখে।
উদাহরণ: Null Handling in Collections
public class Person {
private String name;
private List<Address> addresses;
// Getters and Setters
}
public class Address {
private String city;
private String street;
// Getters and Setters
}
public class PersonDTO {
private String name;
private List<String> cities;
// Getters and Setters
}
@Mapper
public interface PersonMapper {
@Mapping(source = "addresses", target = "cities")
PersonDTO personToPersonDTO(Person person);
}
এখানে, addresses List থেকে cities List এ ম্যাপিং করা হচ্ছে এবং যদি কোনো Address অবজেক্ট null হয়, তবে cities List এ সেট করা হবে null।
৮. Null Value Handling with Optional
MapStruct Optional ব্যবহারেও null হ্যান্ডলিং সমর্থন করে। Optional ব্যবহার করে আপনি আরো নিরাপদভাবে null চেক করতে পারেন।
উদাহরণ: Null Handling with Optional
public class Person {
private Optional<String> name;
// Getters and Setters
}
public class PersonDTO {
private String name;
// Getters and Setters
}
@Mapper
public interface PersonMapper {
@Mapping(source = "name", target = "name")
PersonDTO personToPersonDTO(Person person);
default String mapOptionalName(Optional<String> name) {
return name.orElse("Default Name");
}
}
এখানে, Optional থেকে String ম্যাপ করতে orElse() মেথড ব্যবহার করা হয়েছে।
সারাংশ
MapStruct ব্যবহার করে null value handling করা খুবই সহজ এবং শক্তিশালী। এটি বিভিন্ন কৌশল ব্যবহার করে null চেক এবং ডিফল্ট মান নির্ধারণ করতে সহায়তা করে। আপনি @Mapping অ্যানোটেশন ব্যবহার করে null ভ্যালু হ্যান্ডলিং কাস্টমাইজ করতে পারেন, কাস্টম ম্যাপিং মেথড তৈরি করতে পারেন, এবং কাস্টম ডিফল্ট মান নির্ধারণ করতে পারেন। এছাড়া, nested objects, collections, এবং Optional এর ক্ষেত্রেও null value handling সম্পাদন করা সম্ভব।
Read more