Hibernate Inheritance Mapping হল Hibernate ORM এর একটি বৈশিষ্ট্য যা inheritance (উত্তরণ) সম্পর্কিত ধারণাগুলিকে Object-Relational Mapping (ORM)-এর মাধ্যমে ডেটাবেস টেবিলের সাথে সম্পর্কিত করে। এর মাধ্যমে আপনি Java ক্লাসে বিভিন্ন ধরনের inheritance পদ্ধতি ব্যবহার করতে পারেন, যেমন single-table inheritance, joined-table inheritance, এবং table-per-class inheritance। Hibernate ডাটাবেসের সাথে inheritance relationship ম্যাপ করতে সহায়তা করে।
Hibernate Inheritance Mapping আপনাকে একই অ্যাপ্লিকেশনে class hierarchy পরিচালনা করতে সক্ষম করে, যেখানে পেরেন্ট এবং চাইল্ড ক্লাসের ডেটাবেস টেবিলগুলিকে উপযুক্তভাবে ম্যাপ করা হয়।
এখানে Hibernate Inheritance Mapping এর বিভিন্ন স্ট্রাটেজি সম্পর্কে বিস্তারিত আলোচনা করা হয়েছে:
Hibernate Inheritance Mapping এর স্ট্রাটেজি:
Hibernate-এ তিনটি প্রধান inheritance mapping স্ট্রাটেজি রয়েছে:
- Single Table Inheritance (একটি টেবিলে সব ক্লাসের ডেটা রাখা)
- Joined Table Inheritance (প্রতিটি ক্লাসের জন্য আলাদা টেবিল তৈরি করা)
- Table per Class Inheritance (প্রতিটি ক্লাসের জন্য আলাদা টেবিল এবং কলাম তৈরি করা)
1. Single Table Inheritance
এই স্ট্রাটেজিতে সমস্ত ক্লাস (পেরেন্ট এবং চাইল্ড) একটিমাত্র টেবিলে ম্যাপ করা হয়। সমস্ত ক্লাসের জন্য একটি বড় টেবিল তৈরি হয় এবং সেখানে একটি স্পেশাল কলাম থাকে যা discriminator হিসেবে কাজ করে, যাতে Hibernate জানে কোন রেকর্ড কোন ক্লাসের অন্তর্ভুক্ত।
Single Table Inheritance Mapping Example:
import javax.persistence.Entity;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Id;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "vehicle_type", discriminatorType = DiscriminatorType.STRING)
public class Vehicle {
@Id
private int id;
private String brand;
// Getter and Setter methods
}
@Entity
public class Car extends Vehicle {
private int doors;
// Getter and Setter methods
}
@Entity
public class Bike extends Vehicle {
private boolean hasCarrier;
// Getter and Setter methods
}
এখানে, Vehicle ক্লাস পেরেন্ট হিসেবে কাজ করছে, এবং Car ও Bike হল চাইল্ড ক্লাস। @Inheritance(strategy = InheritanceType.SINGLE_TABLE) নির্দেশ করে যে সব ক্লাসের ডেটা এক টেবিলে থাকবে।
এই ক্ষেত্রে, Hibernate একাধিক discriminator column ব্যবহার করে vehicle_type কলামটি নির্ধারণ করবে, যাতে এটি বুঝতে পারে কোন রেকর্ড Car বা Bike ক্লাসের অন্তর্গত।
টেবিলের স্ট্রাকচার:
+----+--------+--------------+------+
| id | brand | vehicle_type | ... |
+----+--------+--------------+------+
| 1 | Toyota | Car | ... |
| 2 | Yamaha | Bike | ... |
+----+--------+--------------+------+
2. Joined Table Inheritance
এই স্ট্রাটেজিতে, পেরেন্ট এবং চাইল্ড ক্লাসের জন্য আলাদা টেবিল তৈরি করা হয়, তবে একে অপরের সাথে JOIN করা হয়। পেরেন্ট ক্লাসের টেবিলটি মূলত সমস্ত সাধারণ তথ্য ধারণ করবে এবং চাইল্ড ক্লাসের টেবিলগুলি শুধুমাত্র তাদের নির্দিষ্ট বৈশিষ্ট্য ধারণ করবে।
Joined Table Inheritance Mapping Example:
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Id;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Vehicle {
@Id
private int id;
private String brand;
// Getter and Setter methods
}
@Entity
public class Car extends Vehicle {
private int doors;
// Getter and Setter methods
}
@Entity
public class Bike extends Vehicle {
private boolean hasCarrier;
// Getter and Setter methods
}
এখানে, Vehicle ক্লাস পেরেন্ট ক্লাস হিসেবে কাজ করছে এবং Car এবং Bike ক্লাস আলাদা টেবিল তৈরি করবে। Hibernate একে অপরের সাথে JOIN করে তথ্য সংগ্রহ করবে।
টেবিলের স্ট্রাকচার:
- Vehicle টেবিল:
+----+--------+
| id | brand |
+----+--------+
| 1 | Toyota |
| 2 | Yamaha |
+----+--------+
- Car টেবিল:
+----+--------+------+
| id | brand | doors|
+----+--------+------+
| 1 | Toyota | 4 |
+----+--------+------+
- Bike টেবিল:
+----+--------+------------+
| id | brand | hasCarrier |
+----+--------+------------+
| 2 | Yamaha | true |
+----+--------+------------+
3. Table per Class Inheritance
এই স্ট্রাটেজিতে, প্রতিটি ক্লাসের জন্য একটি আলাদা টেবিল তৈরি করা হয় এবং প্রতিটি টেবিলের মধ্যে পেরেন্ট ক্লাসের সকল প্রপার্টি কপি করা হয়। এতে ডেটাবেসের টেবিল গুলো অদ্বিতীয় হয় এবং ডেটা রিড বা রাইট করার জন্য ভিন্ন টেবিল ব্যবহৃত হয়।
Table per Class Inheritance Mapping Example:
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Id;
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Vehicle {
@Id
private int id;
private String brand;
// Getter and Setter methods
}
@Entity
public class Car extends Vehicle {
private int doors;
// Getter and Setter methods
}
@Entity
public class Bike extends Vehicle {
private boolean hasCarrier;
// Getter and Setter methods
}
এখানে, Vehicle, Car, এবং Bike প্রতিটি ক্লাসের জন্য আলাদা টেবিল তৈরি হবে।
টেবিলের স্ট্রাকচার:
- Vehicle টেবিল:
+----+--------+
| id | brand |
+----+--------+
| 1 | Toyota |
| 2 | Yamaha |
+----+--------+
- Car টেবিল:
+----+--------+------+
| id | brand | doors|
+----+--------+------+
| 1 | Toyota | 4 |
+----+--------+------+
- Bike টেবিল:
+----+--------+------------+
| id | brand | hasCarrier |
+----+--------+------------+
| 2 | Yamaha | true |
+----+--------+------------+
Hibernate Inheritance Mapping এর সুবিধা:
- Single Table Inheritance:
- সুবিধা: সহজে ব্যবহারযোগ্য এবং ডেটাবেসের সংখ্যা কমায়।
- সীমাবদ্ধতা: যদি অনেক child classes থাকে, তাহলে টেবিলটি অনেক বড় হয়ে যেতে পারে, যেটি পারফরম্যান্স কমাতে পারে।
- Joined Table Inheritance:
- সুবিধা: ডেটাবেসে বেশি স্পষ্টভাবে normalized data থাকে এবং redundancy কম থাকে।
- সীমাবদ্ধতা: টেবিলগুলোর মধ্যে JOIN করার ফলে পারফরম্যান্স কিছুটা কমে যেতে পারে।
- Table per Class Inheritance:
- সুবিধা: প্রতিটি ক্লাসের জন্য আলাদা টেবিল থাকার কারণে ডেটার কাঠামো পরিষ্কার থাকে।
- সীমাবদ্ধতা: একাধিক টেবিল ব্যবহারের কারণে ডেটা duplication হতে পারে, যা স্টোরেজের পরিমাণ বাড়ায়।
Hibernate-এ Inheritance Mapping ব্যবহার করার মাধ্যমে আপনি আপনার অ্যাপ্লিকেশনের মধ্যে class hierarchy সঠিকভাবে পরিচালনা করতে পারেন। এটি আপনাকে single-table, joined-table, অথবা table-per-class স্ট্রাটেজি অনুযায়ী ডেটাবেসের টেবিলগুলির মধ্যে সম্পর্ক স্থাপন করতে সহায়তা করে। আপনি আপনার অ্যাপ্লিকেশনের জন্য সবচেয়ে উপযুক্ত স্ট্রাটেজি বেছে নেবেন, যা performance, data redundancy, এবং maintenance এর জন্য সবচেয়ে কার্যকরী হবে।
Hibernate ORM (Object-Relational Mapping) ফ্রেমওয়ার্ক, ডেটাবেসের object-oriented ডেটা মডেল এবং relational database টেবিলের মধ্যে সম্পর্ক স্থাপন করতে ব্যবহৃত হয়। Hibernate Inheritance Mapping একটি অত্যন্ত গুরুত্বপূর্ণ ফিচার যা inheritance relationship (উত্তরাধিকার সম্পর্ক) ম্যানেজ করতে সাহায্য করে, যেখানে এক ক্লাস (superclass) এবং তার উপশ্রেণী (subclasses) এর মধ্যে সম্পর্ক স্থাপন করা হয়।
Hibernate এ Inheritance Mapping ব্যবহৃত হয় যখন Java ক্লাসের মধ্যে ইনহেরিটেন্স (inheritance) ব্যবহার করা হয়, এবং আপনাকে সেগুলোকে ডেটাবেসে ম্যাপ করতে হয়। Hibernate তিনটি মূল inheritance strategies প্রদান করে:
- Single Table Inheritance (একটি টেবিল ব্যবহার)
- Joined Table Inheritance (এবং আলাদা টেবিল ব্যবহার)
- Table per Class Inheritance (প্রতিটি ক্লাসের জন্য একটি টেবিল ব্যবহার)
1. Single Table Inheritance
এই স্ট্রাটেজিতে, সমস্ত ইনহেরিটেন্স সম্পর্কিত ক্লাসগুলোর জন্য একটিমাত্র টেবিল ব্যবহার করা হয়। সমস্ত প্রপার্টি (superclass এবং subclass) একটি টেবিলের মধ্যে সংরক্ষিত হয়। @DiscriminatorColumn এবং @DiscriminatorValue অ্যানোটেশনগুলি দিয়ে নির্ধারণ করা হয় কোন ক্লাসের কোন রেকর্ড।
Advantages:
- Simple: সব ক্লাসের জন্য একটি টেবিল ব্যবহার করে ডেটা সংরক্ষণ করা হয়।
- Performance: একটি টেবিলের মাধ্যমে সব ইনহেরিটেড ডেটা পাওয়া যায়, তাই কিছু ক্ষেত্রে এটি দ্রুত হতে পারে।
Disadvantages:
- Unused Columns: উপশ্রেণীগুলির জন্য কিছু কলাম হয়তো ব্যবহার হবে না, কিন্তু সেগুলি টেবিলের অংশ হিসেবে থাকবে, যা wasted space তৈরি করতে পারে।
Example: Single Table Inheritance
ধরা যাক আমাদের একটি Employee ক্লাস রয়েছে, যা FullTimeEmployee এবং PartTimeEmployee নামে দুটি সাবক্লাস ইনহেরিট করে।
Employee Class (Superclass)
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "employee_type")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// Getters, Setters, Constructors
}
FullTimeEmployee Class (Subclass)
@Entity
@DiscriminatorValue("FullTime")
public class FullTimeEmployee extends Employee {
private double salary;
// Getters, Setters, Constructors
}
PartTimeEmployee Class (Subclass)
@Entity
@DiscriminatorValue("PartTime")
public class PartTimeEmployee extends Employee {
private double hourlyRate;
// Getters, Setters, Constructors
}
এখানে, @DiscriminatorColumn এবং @DiscriminatorValue ব্যবহার করা হয়েছে যাতে FullTimeEmployee এবং PartTimeEmployee ক্লাসগুলো আলাদা করে ডেটাবেসে সংরক্ষিত হয়।
2. Joined Table Inheritance
এই স্ট্রাটেজিতে, প্রতিটি ক্লাসের জন্য একটি আলাদা টেবিল তৈরি হয় এবং তাদের মধ্যে একটি join সম্পর্ক থাকে। Superclass টেবিলের মধ্যে সাধারণ প্রপার্টি থাকবে, এবং subclasses তাদের নিজস্ব টেবিলের মধ্যে নির্দিষ্ট প্রপার্টি সংরক্ষণ করবে। এই পদ্ধতিতে normalization উন্নত হয় এবং data redundancy কম থাকে।
Advantages:
- Normalization: প্রতিটি ক্লাসের জন্য একটি আলাদা টেবিল থাকার কারণে ডেটাবেসে সাধারণ প্রপার্টি পুনরাবৃত্তি করা হয় না।
- Flexibility: নতুন সাবক্লাস যোগ করতে হলে সহজভাবে টেবিলের মধ্যে নতুন কলাম যোগ করা যায়।
Disadvantages:
- Performance: টেবিলগুলোর মধ্যে join করতে হয়, তাই এটি slower হতে পারে, বিশেষত যখন অনেক ইনহেরিটেড ক্লাস থাকে।
Example: Joined Table Inheritance
ধরা যাক আমাদের আবারও Employee এবং এর দুটি সাবক্লাস FullTimeEmployee এবং PartTimeEmployee আছে।
Employee Class (Superclass)
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// Getters, Setters, Constructors
}
FullTimeEmployee Class (Subclass)
@Entity
public class FullTimeEmployee extends Employee {
private double salary;
// Getters, Setters, Constructors
}
PartTimeEmployee Class (Subclass)
@Entity
public class PartTimeEmployee extends Employee {
private double hourlyRate;
// Getters, Setters, Constructors
}
এখানে, @Inheritance(strategy = InheritanceType.JOINED) ব্যবহার করা হয়েছে, যার মাধ্যমে সব ক্লাসের জন্য আলাদা টেবিল তৈরি করা হয় এবং Employee টেবিলটি অন্য টেবিলগুলির সাথে join হয়ে থাকে।
3. Table per Class Inheritance
এই স্ট্রাটেজিতে, প্রতিটি ক্লাসের জন্য সম্পূর্ণ একটি আলাদা টেবিল তৈরি হয়। প্রতিটি টেবিল তার নিজস্ব প্রপার্টি এবং ইনহেরিটেড প্রপার্টি সংরক্ষণ করে। কোনো join সম্পর্ক থাকে না এবং একেবারে আলাদা টেবিল ব্যবহৃত হয়।
Advantages:
- Data Isolation: প্রতিটি ক্লাসের জন্য আলাদা টেবিল থাকায় ডেটা সম্পূর্ণ আলাদা এবং সুরক্ষিত থাকে।
- Performance: কোনো join সম্পর্ক না থাকার কারণে কিছু ক্ষেত্রে এটি দ্রুত হতে পারে।
Disadvantages:
- Redundancy: সবার জন্য সাধারণ প্রপার্টি পুনরাবৃত্তি হতে পারে, বিশেষত যদি superclass এবং subclasses মধ্যে একাধিক সাধারণ প্রপার্টি থাকে।
Example: Table per Class Inheritance
এখানে, Employee এবং তার সাবক্লাসগুলোর জন্য আলাদা টেবিল তৈরি করা হবে।
Employee Class (Superclass)
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// Getters, Setters, Constructors
}
FullTimeEmployee Class (Subclass)
@Entity
public class FullTimeEmployee extends Employee {
private double salary;
// Getters, Setters, Constructors
}
PartTimeEmployee Class (Subclass)
@Entity
public class PartTimeEmployee extends Employee {
private double hourlyRate;
// Getters, Setters, Constructors
}
এখানে, @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) ব্যবহার করা হয়েছে, যার মাধ্যমে Employee, FullTimeEmployee, এবং PartTimeEmployee ক্লাসের জন্য আলাদা টেবিল তৈরি হবে।
সামগ্রিকভাবে Inheritance Mapping
Hibernate এর Inheritance Mapping তিনটি স্ট্রাটেজি মাধ্যমে ডেটাবেসের সাথে অবজেক্ট ইনহেরিটেন্স সম্পর্ক তৈরি করতে সহায়ক:
- Single Table Inheritance: একক টেবিল ব্যবহৃত হয়, তবে কিছু ক্ষেত্র মিসিং বা অপ্রয়োজনীয় হতে পারে।
- Joined Table Inheritance: প্রতিটি ক্লাসের জন্য একটি আলাদা টেবিল থাকে এবং এই টেবিলগুলোর মধ্যে join করা হয়।
- Table per Class Inheritance: প্রতিটি ক্লাসের জন্য সম্পূর্ণ আলাদা টেবিল তৈরি হয় এবং কোন join সম্পর্ক থাকে না।
প্রতিটি স্ট্রাটেজির নিজস্ব সুবিধা এবং অসুবিধা রয়েছে, এবং আপনি আপনার অ্যাপ্লিকেশনটির প্রয়োজন অনুসারে সবচেয়ে উপযুক্ত স্ট্রাটেজি নির্বাচন করতে পারেন। Single Table স্ট্রাটেজি সাধারণত দ্রুত এবং সহজ, কিন্তু Joined এবং Table per Class স্ট্রাটেজি সাধারণত data normalization এর জন্য ভালো।
Single Table Strategy হল Hibernate ORM-এ Inheritance Mapping পদ্ধতির একটি ধরন, যেখানে সমস্ত অবজেক্টের ডেটা একটি একক টেবিলেই সংরক্ষিত হয়, এবং ইনহেরিটেড ক্লাসের মধ্যে পার্থক্য চিহ্নিত করার জন্য একটি বিশেষ কলাম ব্যবহৃত হয়। এটি Inheritance Mapping এর মধ্যে সবচেয়ে সহজ পদ্ধতি, কারণ এখানে সমস্ত ডেটা একটি মাত্র টেবিলের মধ্যে থাকে এবং পারেন্ট এবং চাইল্ড ক্লাসের সকল ডেটা একই টেবিলে সংরক্ষিত হয়।
Single Table Inheritance Strategy: কীভাবে কাজ করে?
Hibernate এর Single Table Strategy-এ:
- Parent class এবং Child classes সবগুলোই একই টেবিলে সংরক্ষিত হয়।
- একটি Discriminator column (যেটি সাধারণত
@DiscriminatorColumnঅ্যানোটেশন দ্বারা চিহ্নিত হয়) থাকে যা নির্ধারণ করে কোন রেকর্ডটি কোন ক্লাসের অন্তর্গত। এই কলামটি type বা class type নির্দেশ করে। - যখন Hibernate কনফিগার করা হয়, তখন এটি সমস্ত ইনহেরিটেড ক্লাসের জন্য একক টেবিল তৈরি করে, এবং এই টেবিলের প্রতিটি রেকর্ড একটি নির্দিষ্ট ক্লাসের প্রতিনিধিত্ব করে।
Single Table Strategy এর উপকারিতা:
- Performance: একক টেবিলে সমস্ত ডেটা সংরক্ষণ করার কারণে ডেটা অ্যাক্সেস দ্রুত হতে পারে কারণ কোনো JOIN অপারেশন প্রয়োজন হয় না।
- Simplicity: এই স্ট্রাটেজি ব্যবহার করে টেবিলের সংখ্যা কম থাকে এবং অ্যাপ্লিকেশন ব্যবস্থাপনা সহজ হয়।
- Less Join Operations: যখন ইনহেরিটেন্স স্ট্রাকচার খুব গভীর না হয়, তখন Single Table Strategy-এ জয়েন অপারেশনগুলির প্রয়োজন হয় না, যার ফলে পারফরম্যান্স উন্নত হয়।
Single Table Strategy এর সীমাবদ্ধতা:
- Data Redundancy: যদি চাইল্ড ক্লাসগুলির মধ্যে অনেক ক্ষেত্র সমান থাকে, তবে এগুলি একসাথে সংরক্ষণ করার ফলে ডেটা পুনরাবৃত্তি হতে পারে।
- Large Tables: একক টেবিলের মধ্যে অনেক তথ্য রাখলে টেবিলটি বড় হয়ে যেতে পারে, বিশেষত যদি ইনহেরিটেন্স স্ট্রাকচারটি গভীর হয় বা অনেক সাবক্লাস থাকে।
- Inheritance Constraints: যদি আপনি অনেক আলাদা টাইপের ডেটা সংরক্ষণ করতে চান, তবে একক টেবিলে এগুলিকে চিহ্নিত করা কঠিন হতে পারে।
Single Table Strategy এর উদাহরণ
ধরা যাক, আমাদের দুটি ক্লাস আছে: Employee (Parent class) এবং Manager, Developer (Child classes)। আমরা Single Table Strategy ব্যবহার করব।
Step 1: Parent এবং Child Classes তৈরি করা
import javax.persistence.*;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "employee_type", discriminatorType = DiscriminatorType.STRING)
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String department;
// Getters and Setters
}
@Entity
@DiscriminatorValue("Manager")
public class Manager extends Employee {
private int teamSize;
// Getters and Setters
}
@Entity
@DiscriminatorValue("Developer")
public class Developer extends Employee {
private String programmingLanguage;
// Getters and Setters
}
এখানে:
@Inheritance(strategy = InheritanceType.SINGLE_TABLE): এটি বলে দেয় যে ইনহেরিটেন্স স্ট্রাটেজি হল Single Table।@DiscriminatorColumn(name = "employee_type", discriminatorType = DiscriminatorType.STRING): এটিemployee_typeনামের একটি কলাম তৈরি করবে, যা প্রতিটি রেকর্ডের জন্য ক্লাস টাইপ চিহ্নিত করবে (যেমনManagerবাDeveloper)।@DiscriminatorValue("Manager")এবং@DiscriminatorValue("Developer"): এগুলি চাইল্ড ক্লাসের জন্য নির্দিষ্ট ডিসক্রিমিনেটর ভ্যালু হিসেবে কাজ করবে।
Step 2: Database Table Structure
এই কোডের মাধ্যমে Hibernate একটি টেবিল তৈরি করবে, যার নাম হবে Employee (বা আপনার ক্লাসের নাম অনুযায়ী)। এই টেবিলে সমস্ত Employee, Manager, এবং Developer রেকর্ড থাকবে। প্রতিটি রেকর্ডের জন্য employee_type কলামটি ব্যবহৃত হবে, যা এই রেকর্ডটির জন্য ডিসক্রিমিনেটর ভ্যালু (যেমন Manager বা Developer) ধারণ করবে।
Employee Table Structure:
| id | name | department | employee_type | teamSize | programmingLanguage |
|---|---|---|---|---|---|
| 1 | John | HR | Manager | 10 | NULL |
| 2 | Alice | IT | Developer | NULL | Java |
| 3 | Bob | Marketing | Manager | 5 | NULL |
| 4 | Charlie | IT | Developer | NULL | Python |
Step 3: Example of CRUD Operations
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class EmployeeExample {
public static void main(String[] args) {
SessionFactory factory = new Configuration()
.configure("hibernate.cfg.xml")
.addAnnotatedClass(Employee.class)
.addAnnotatedClass(Manager.class)
.addAnnotatedClass(Developer.class)
.buildSessionFactory();
Session session = factory.getCurrentSession();
try {
// Create new Manager and Developer objects
Manager manager = new Manager();
manager.setName("John");
manager.setDepartment("HR");
manager.setTeamSize(10);
Developer developer = new Developer();
developer.setName("Alice");
developer.setDepartment("IT");
developer.setProgrammingLanguage("Java");
// Start transaction
session.beginTransaction();
// Save both objects
session.save(manager);
session.save(developer);
// Commit transaction
session.getTransaction().commit();
System.out.println("Saved manager and developer successfully!");
} finally {
factory.close();
}
}
}
Single Table Strategy-এর Advantages
- Performance: একটিমাত্র টেবিলে সমস্ত ডেটা থাকার কারণে ডেটাবেস অপারেশনগুলি (যেমন
SELECT,UPDATE,DELETE) দ্রুত হতে পারে, কারণ JOIN অপারেশন করার প্রয়োজন নেই। - Simplicity: এক টেবিলে সমস্ত তথ্য রাখার কারণে ডেটাবেসের স্ট্রাকচার সহজ হয়। ইনহেরিটেন্সের জন্য আলাদা আলাদা টেবিলের প্রয়োজন হয় না।
- Less Complexity: একক টেবিলে সব ডেটা সংরক্ষণ করার ফলে, টেবিলের মধ্যে সম্পর্ক ব্যবস্থাপনা সহজ হয়ে যায়।
Single Table Strategy-এর Disadvantages
- Data Redundancy: যেহেতু সব ডেটা একই টেবিলের মধ্যে থাকে, চাইল্ড ক্লাসে অতিরিক্ত প্রপার্টি থাকলে ডেটা পুনরাবৃত্তি হতে পারে।
- Table Size: এক টেবিলে অনেক ডেটা সংরক্ষণ করতে হলে টেবিলটি খুব বড় হয়ে যেতে পারে, যা পারফরম্যান্স ইস্যু তৈরি করতে পারে।
- Column Explosion: যদি ইনহেরিটেন্স স্ট্রাকচার খুব বড় হয়, তবে অনেক নতুন কলাম যোগ করতে হতে পারে, যা টেবিলের ডেটা ম্যানেজমেন্ট কঠিন করে তোলে।
Hibernate-এ Single Table Strategy হল একটি ইনহেরিটেন্স ম্যাপিং কৌশল যা Object-Relational Mapping (ORM) সম্পর্কিত ডেটা সহজে সংরক্ষণ এবং পরিচালনা করার জন্য ব্যবহৃত হয়। এটি performance এবং simplicity প্রদান করে, তবে data redundancy এবং scalability issues হতে পারে, বিশেষত বড় ইনহেরিটেন্স স্ট্রাকচার থাকলে।
এই কৌশলটি ছোট এবং মাঝারি ইনহেরিটেন্স কাঠামো যেখানে ডেটার পুনরাবৃত্তি কম এবং খুব বেশি কলাম বাড়ানোর প্রয়োজন নেই, সেখানে খুব উপযোগী।
Hibernate-এ Joined Table Strategy হল Inheritance Mapping এর একটি পদ্ধতি যা আপনি ব্যবহার করতে পারেন যখন আপনার জাভা ক্লাসগুলি একে অপরের সাথে সম্পর্কিত হয় এবং আপনি চান যে ডাটাবেসে পৃথক টেবিলগুলিতে এই সম্পর্কগুলিকে সংরক্ষণ করা হোক। এটি Single Table Strategy এবং Table per Subclass থেকে আলাদা, কারণ এটি ইনহেরিটেড ক্লাসের জন্য পৃথক টেবিল তৈরি করে এবং তাদের মধ্যে একটি join তৈরি করে।
Joined Table Strategy:
Hibernate-এ Joined Table Strategy হল একটি পদ্ধতি যেখানে superclass এবং subclass ক্লাসগুলির জন্য আলাদা আলাদা টেবিল তৈরি করা হয় এবং তারপরে একটি JOIN ব্যবহার করে তাদের মধ্যে সম্পর্ক স্থাপন করা হয়। এর মাধ্যমে, আপনি আপনার ইনহেরিটেন্স হায়ারার্কি (superclass ও subclass) ডাটাবেসে পৃথক টেবিল হিসেবে সংরক্ষণ করতে পারেন।
Conceptual Overview:
- Superclass এর জন্য একটি টেবিল থাকবে।
- Subclass এর জন্য আলাদা একটি টেবিল থাকবে।
- সবগুলো টেবিলের মধ্যে JOIN হবে
@PrimaryKeyJoinColumnব্যবহার করে। @Inheritance(strategy = InheritanceType.JOINED)ব্যবহার করলে Hibernate জানবে যে এটি Joined Table Strategy।
Use Case:
যদি আপনার এমন একটি পরিস্থিতি থাকে যেখানে আপনি Inheritance ব্যবহার করছেন এবং আপনার ক্লাসের বিভিন্ন সাবক্লাসগুলির জন্য আলাদা টেবিল প্রয়োজন, তবে Joined Table Strategy কার্যকর হতে পারে। এতে প্রতিটি সাবক্লাসের জন্য পৃথক টেবিল থাকবে এবং সেই টেবিলগুলি মূল টেবিলের সাথে join করা হবে। এটি ডেটা সঞ্চয় করার জন্য আরও নর্মালাইজড একটি কাঠামো সরবরাহ করে।
Example: Joined Table Strategy in Hibernate
Step 1: Create the Entity Classes
এখানে, আমরা একটি Employee ক্লাস এবং তার সাবক্লাস FullTimeEmployee এবং PartTimeEmployee তৈরি করব।
Superclass (Employee)
import javax.persistence.*;
@Entity
@Inheritance(strategy = InheritanceType.JOINED) // Specify JOINED inheritance strategy
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
public Employee() {}
public Employee(String name) {
this.name = name;
}
// Getters and setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
এখানে, Employee ক্লাসটি সুপারক্লাস হিসেবে কাজ করছে এবং @Inheritance(strategy = InheritanceType.JOINED) অ্যানোটেশনটি ব্যবহার করা হয়েছে যাতে Hibernate জানে যে এটি Joined Table Strategy ব্যবহার করবে।
Subclass (FullTimeEmployee)
import javax.persistence.*;
@Entity
public class FullTimeEmployee extends Employee {
private double salary;
public FullTimeEmployee() {}
public FullTimeEmployee(String name, double salary) {
super(name);
this.salary = salary;
}
// Getters and setters
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
এখানে, FullTimeEmployee ক্লাসটি Employee ক্লাস থেকে ইনহেরিট করেছে এবং এর নিজস্ব salary ফিল্ড রয়েছে।
Subclass (PartTimeEmployee)
import javax.persistence.*;
@Entity
public class PartTimeEmployee extends Employee {
private int hoursWorked;
public PartTimeEmployee() {}
public PartTimeEmployee(String name, int hoursWorked) {
super(name);
this.hoursWorked = hoursWorked;
}
// Getters and setters
public int getHoursWorked() {
return hoursWorked;
}
public void setHoursWorked(int hoursWorked) {
this.hoursWorked = hoursWorked;
}
}
এখানে, PartTimeEmployee ক্লাসটি Employee থেকে ইনহেরিট করেছে এবং এর নিজস্ব hoursWorked ফিল্ড রয়েছে।
Step 2: Hibernate Configuration
Hibernate কনফিগারেশন ফাইল hibernate.cfg.xml তৈরি করুন যাতে ডাটাবেস সংযোগের সমস্ত প্রপার্টি এবং টেবিল সম্পর্কিত কনফিগারেশন থাকে।
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- JDBC Database connection settings -->
<property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
<property name="hibernate.connection.driver_class">org.h2.Driver</property>
<property name="hibernate.connection.url">jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<!-- Enable Hibernate's automatic session context management -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- Show SQL -->
<property name="hibernate.show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- Mention the annotated class -->
<mapping class="com.example.hibernate.Employee"/>
<mapping class="com.example.hibernate.FullTimeEmployee"/>
<mapping class="com.example.hibernate.PartTimeEmployee"/>
</session-factory>
</hibernate-configuration>
এখানে, hibernate.cfg.xml ফাইলে ডাটাবেস সংযোগ এবং Hibernate কনফিগারেশন সম্পর্কিত সমস্ত তথ্য দেওয়া হয়েছে।
Step 3: Using Hibernate to Save Data
এখন, আমরা Session এবং Transaction ব্যবহার করে ডেটা সেভ করব। যখন আপনি Joined Table Strategy ব্যবহার করেন, Hibernate দুটি টেবিল তৈরি করবে — একটি Employee টেবিল এবং অন্যটি FullTimeEmployee বা PartTimeEmployee টেবিল।
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
public class MainApp {
public static void main(String[] args) {
// Hibernate configuration and session factory setup
SessionFactory sessionFactory = new org.hibernate.cfg.Configuration()
.configure("hibernate.cfg.xml")
.addAnnotatedClass(Employee.class)
.addAnnotatedClass(FullTimeEmployee.class)
.addAnnotatedClass(PartTimeEmployee.class)
.buildSessionFactory();
// Creating session
Session session = sessionFactory.getCurrentSession();
try {
// Start a transaction
Transaction transaction = session.beginTransaction();
// Create FullTimeEmployee instance
FullTimeEmployee fullTimeEmployee = new FullTimeEmployee("John", 50000);
// Save the object
session.save(fullTimeEmployee);
// Commit the transaction
transaction.commit();
System.out.println("Employee saved successfully!");
} finally {
sessionFactory.close();
}
}
}
এখানে, FullTimeEmployee অবজেক্ট তৈরি করে সেভ করা হচ্ছে। Hibernate Employee টেবিলের জন্য একটি রেকর্ড তৈরি করবে এবং FullTimeEmployee টেবিলের জন্য আলাদা একটি রেকর্ড তৈরি করবে, যেটি Employee টেবিলের সঙ্গে JOIN হয়ে থাকবে।
Step 4: Database Schema
Hibernate Joined Table Strategy ব্যবহার করলে ডাটাবেসে দুটি টেবিল তৈরি হবে:
Employee টেবিল (Superclass):
CREATE TABLE Employee ( id INT PRIMARY KEY, name VARCHAR(255) );FullTimeEmployee টেবিল (Subclass):
CREATE TABLE FullTimeEmployee ( id INT PRIMARY KEY, salary DOUBLE, FOREIGN KEY (id) REFERENCES Employee(id) );
Advantages of Using the Joined Table Strategy:
- Normalized Database Schema: ডাটাবেসের টেবিলগুলি ভালভাবে নর্মালাইজড থাকে, যার ফলে ডেটা পুনরাবৃত্তি কম হয়।
- Efficient Storage: শুধুমাত্র subclass-specific ডেটা তার নিজস্ব টেবিলে সংরক্ষণ করা হয়, এবং superclass-এর সাধারণ ডেটা একটি আলাদা টেবিলে রাখা হয়।
- Clear Data Separation: আলাদা টেবিলগুলি মেনটেন করে, ক্লাসগুলির মধ্যে সম্পর্ক স্পষ্টভাবে পরিস্কার থাকে।
Disadvantages of Using the Joined Table Strategy:
- Join Complexity: একাধিক টেবিলের মধ্যে JOIN করার ফলে কিছুটা জটিলতা এবং পারফরম্যান্স সমস্যা হতে পারে, বিশেষ করে বড় ডেটাসেটে।
- Increased Query Complexity: আপনাকে বারবার
JOINকরতে হতে পারে, যা কিছু পরিমাণে কোড এবং কুয়েরি জটিল করতে পারে।
Hibernate-এর Joined Table Strategy ব্যবহার করে আপনি Inheritance Mapping এবং Normalization করতে পারেন, যেখানে আপনার superclass এবং subclass এর জন্য পৃথক টেবিল তৈরি হয় এবং তাদের মধ্যে সম্পর্ক JOIN এর মাধ্যমে স্থাপন করা হয়। এই পদ্ধতি ডেটাবেসের টেবিলগুলিকে আরও মডুলার এবং পরিষ্কারভাবে তৈরি করতে সাহায্য করে, তবে কিছু ক্ষেত্রে JOIN এর কারণে পারফরম্যান্স সমস্যাও হতে পারে।
Hibernate-এ Table per Class Strategy একটি ইনহেরিটেন্স স্ট্রাটেজি যা Single Table Inheritance থেকে ভিন্ন। এই স্ট্রাটেজিতে, প্রতিটি ক্লাস (বিশেষত সুপার ক্লাস এবং সাব ক্লাস) আলাদা আলাদা টেবিল হিসেবে ডাটাবেসে সংরক্ষিত হয়। এটি "Concrete Table Inheritance" নামেও পরিচিত, কারণ সব ক্লাসের জন্য আলাদা টেবিল তৈরি করা হয় এবং তাদের মধ্যে সম্পর্ক সাধারণত Join এর মাধ্যমে স্থাপন করা হয় না।
Table per Class Strategy-এর মূল ধারণা:
- Superclass এবং Subclass এর জন্য আলাদা টেবিল তৈরি করা হয়।
- প্রতিটি টেবিলেই কেবল তার নিজস্ব প্রপার্টি থাকে, এবং যদি সাবক্লাসে অতিরিক্ত প্রপার্টি থাকে, সেগুলি শুধুমাত্র সেই ক্লাসের টেবিলে থাকে।
- ডাটা ডুপ্লিকেশন: সবার জন্য আলাদা টেবিল থাকায় কিছু ডাটা ডুপ্লিকেশন হতে পারে, যেমন, একই তথ্য বারবার প্রতিটি টেবিলে থাকতে পারে।
Table per Class Strategy এর সুবিধা ও অসুবিধা
সুবিধা:
- Performance: বড় ডাটাবেসে যেখানে সম্পর্ক কম গুরুত্বপূর্ণ, সেখানে এই স্ট্রাটেজি কার্যকর হতে পারে।
- Simplified Model: এখানে জটিল
JOINঅপারেশনের প্রয়োজন হয় না, কারণ প্রতিটি ক্লাসের জন্য আলাদা টেবিল থাকে।
অসুবিধা:
- ডাটা ডুপ্লিকেশন: সুপার ক্লাসের সকল কলাম প্রতিটি সাব ক্লাসে পুনরাবৃত্তি হয়, যা ডাটাবেসে ডুপ্লিকেশন সৃষ্টি করে।
- এডমিনিস্ট্রেশন: বিভিন্ন টেবিলের ব্যবস্থাপনা আরও কঠিন হতে পারে এবং কোডিং এবং মেইনটেন্যান্স জটিল হতে পারে।
Example of Table per Class Strategy in Hibernate
ধরা যাক, আমাদের একটি Employee সুপার ক্লাস রয়েছে এবং এটি দুটি সাব ক্লাস FullTimeEmployee এবং PartTimeEmployee তে ইনহেরিট করা হয়।
Step 1: Define the Superclass and Subclasses
- Superclass:
Employee
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Employee {
@Id
private int id;
private String name;
// Getters and Setters
}
- Subclass:
FullTimeEmployee
import javax.persistence.Entity;
@Entity
public class FullTimeEmployee extends Employee {
private double salary;
// Getters and Setters
}
- Subclass:
PartTimeEmployee
import javax.persistence.Entity;
@Entity
public class PartTimeEmployee extends Employee {
private double hourlyRate;
// Getters and Setters
}
Step 2: Configure hibernate.cfg.xml for Table per Class Strategy
Hibernate এর কনফিগারেশন ফাইলে আপনি @Inheritance অ্যানোটেশন ব্যবহার করে স্ট্রাটেজি সিলেক্ট করতে পারবেন। আমরা @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) ব্যবহার করব।
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Employee {
@Id
private int id;
private String name;
// Getters and Setters
}
এখানে, @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) নির্দেশনা দিয়ে Hibernate জানায় যে প্রতিটি ক্লাসের জন্য আলাদা টেবিল তৈরি করতে হবে।
Step 3: Hibernate Mapping (Database Tables)
এখন Hibernate এই Employee, FullTimeEmployee, এবং PartTimeEmployee ক্লাসের জন্য আলাদা টেবিল তৈরি করবে। টেবিলগুলির সিএলএল দেখতে কিছুটা এইরকম হবে:
- Employee Table:
CREATE TABLE Employee (
id INT PRIMARY KEY,
name VARCHAR(255)
);
- FullTimeEmployee Table:
CREATE TABLE FullTimeEmployee (
id INT PRIMARY KEY,
name VARCHAR(255),
salary DOUBLE
);
- PartTimeEmployee Table:
CREATE TABLE PartTimeEmployee (
id INT PRIMARY KEY,
name VARCHAR(255),
hourlyRate DOUBLE
);
Step 4: Saving Data using Table per Class Strategy
এখন আপনি এই টেবিলগুলো ব্যবহার করে ডেটা ইনসার্ট করতে পারেন, যেখানে প্রতিটি ক্লাসের জন্য আলাদা টেবিল থাকবে।
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class EmployeeTest {
public static void main(String[] args) {
SessionFactory factory = new Configuration().configure("hibernate.cfg.xml")
.addAnnotatedClass(FullTimeEmployee.class)
.addAnnotatedClass(PartTimeEmployee.class)
.buildSessionFactory();
Session session = factory.getCurrentSession();
try {
// Create Employee objects
FullTimeEmployee fullTimeEmployee = new FullTimeEmployee();
fullTimeEmployee.setName("John Doe");
fullTimeEmployee.setSalary(50000);
PartTimeEmployee partTimeEmployee = new PartTimeEmployee();
partTimeEmployee.setName("Jane Smith");
partTimeEmployee.setHourlyRate(20);
// Start a transaction
session.beginTransaction();
// Save the employees
session.save(fullTimeEmployee);
session.save(partTimeEmployee);
// Commit transaction
session.getTransaction().commit();
} finally {
factory.close();
}
}
}
Step 5: Querying the Data
এখন যখন আপনি ডেটা রিট্রিভ করবেন, Hibernate বিভিন্ন টেবিল থেকে ডেটা একত্রিত করবে এবং সেগুলিকে অবজেক্টে ম্যাপ করবে। উদাহরণস্বরূপ:
public class EmployeeTest {
public static void main(String[] args) {
SessionFactory factory = new Configuration().configure("hibernate.cfg.xml")
.addAnnotatedClass(FullTimeEmployee.class)
.addAnnotatedClass(PartTimeEmployee.class)
.buildSessionFactory();
Session session = factory.getCurrentSession();
try {
session.beginTransaction();
// Retrieving FullTimeEmployee and PartTimeEmployee
List<FullTimeEmployee> fullTimeEmployees = session.createQuery("from FullTimeEmployee").getResultList();
List<PartTimeEmployee> partTimeEmployees = session.createQuery("from PartTimeEmployee").getResultList();
// Display the results
for (FullTimeEmployee employee : fullTimeEmployees) {
System.out.println("FullTimeEmployee: " + employee.getName() + ", Salary: " + employee.getSalary());
}
for (PartTimeEmployee employee : partTimeEmployees) {
System.out.println("PartTimeEmployee: " + employee.getName() + ", Hourly Rate: " + employee.getHourlyRate());
}
session.getTransaction().commit();
} finally {
factory.close();
}
}
}
Table per Class Strategy Hibernate-এ একটি ইনহেরিটেন্স স্ট্রাটেজি যা প্রতিটি ক্লাসের জন্য আলাদা টেবিল তৈরি করে। এটি ডাটাবেসে Inheritance সম্পর্কিত তথ্য ম্যানেজ করতে সহায়ক। যদিও এটি কিছু ডুপ্লিকেশন তৈরি করতে পারে এবং পারফরম্যান্সে কিছু প্রভাব ফেলতে পারে, তবে যখন ডেটাবেসের সম্পর্কগুলি আলাদা টেবিলের মধ্যে রাখতে হয় এবং জটিল JOIN অপারেশন এড়িয়ে চলা দরকার, তখন এটি উপযুক্ত হয়।
এই স্ট্রাটেজির সাহায্যে আপনি ডেটা অরগানাইজ করতে পারবেন যেখানে প্রতিটি সাব ক্লাসের জন্য আলাদা টেবিল থাকবে এবং আপনাকে বিভিন্ন JOIN অপারেশন করার প্রয়োজন হবে না।
Read more