কম্পোজিট কী কী?
কম্পোজিট কী (Composite Key) হলো একাধিক কলাম বা ফিল্ডের সমন্বয়ে তৈরি একটি প্রাইমারি কী। এটি তখন ব্যবহার করা হয় যখন একটি টেবিলের একক কলাম প্রাইমারি কী হিসেবে পর্যাপ্ত নয়। Hibernate বা JPA এর মাধ্যমে স্প্রিং ORM এ কম্পোজিট কী পরিচালনা করা সম্ভব।
কম্পোজিট কী ব্যবহারের উপায়
Hibernate বা JPA এর মাধ্যমে কম্পোজিট কী ব্যবহারের জন্য @EmbeddedId বা @IdClass এনোটেশন ব্যবহার করা হয়।
পদ্ধতি ১: @EmbeddedId
@EmbeddedId ব্যবহার করে একটি পৃথক Embeddable ক্লাস তৈরি করা হয় যা প্রাইমারি কী হিসাবে ব্যবহৃত হয়।
উদাহরণ
Step 1: Embeddable ক্লাস তৈরি
package com.example.model;
import java.io.Serializable;
import javax.persistence.Embeddable;
@Embeddable
public class CompositeKey implements Serializable {
private int orderId;
private int productId;
// Getters, Setters, hashCode, equals
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
@Override
public int hashCode() {
return orderId + productId;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
CompositeKey that = (CompositeKey) obj;
return orderId == that.orderId && productId == that.productId;
}
}
Step 2: Entity ক্লাস তৈরি
package com.example.model;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
@Entity
public class OrderProduct {
@EmbeddedId
private CompositeKey id;
private int quantity;
// Getters and Setters
public CompositeKey getId() {
return id;
}
public void setId(CompositeKey id) {
this.id = id;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
পদ্ধতি ২: @IdClass
@IdClass ব্যবহার করে একটি পৃথক ক্লাস তৈরি করা হয় যা প্রাইমারি কী ধারণ করে এবং @Id এনোটেশন Entity ক্লাসের মধ্যে প্রত্যেক কী ফিল্ডে যোগ করা হয়।
উদাহরণ
Step 1: Composite Key ক্লাস তৈরি
package com.example.model;
import java.io.Serializable;
public class CompositeKey implements Serializable {
private int orderId;
private int productId;
// Getters, Setters, hashCode, equals
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
@Override
public int hashCode() {
return orderId + productId;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
CompositeKey that = (CompositeKey) obj;
return orderId == that.orderId && productId == that.productId;
}
}
Step 2: Entity ক্লাস তৈরি
package com.example.model;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
@Entity
@IdClass(CompositeKey.class)
public class OrderProduct {
@Id
private int orderId;
@Id
private int productId;
private int quantity;
// Getters and Setters
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
DAO উদাহরণ
DAO স্তরে Hibernate বা JPA এর মাধ্যমে কম্পোজিট কী ব্যবহার করে ডেটা ম্যানিপুলেট করা যায়।
package com.example.dao;
import com.example.model.OrderProduct;
import com.example.model.CompositeKey;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class OrderProductDao {
@Autowired
private SessionFactory sessionFactory;
public void saveOrderProduct(OrderProduct orderProduct) {
Session session = sessionFactory.getCurrentSession();
session.save(orderProduct);
}
public OrderProduct getOrderProduct(CompositeKey id) {
Session session = sessionFactory.getCurrentSession();
return session.get(OrderProduct.class, id);
}
}
গুরুত্বপূর্ণ বিষয়
@EmbeddedIdএবং@IdClassএর মধ্যে পার্থক্য:@EmbeddedId: কম্পোজিট কী সম্পূর্ণ Embeddable অবজেক্ট হিসেবে ব্যবহৃত হয়।@IdClass: কম্পোজিট কী-এর জন্য একটি পৃথক ক্লাস তৈরি করা হয় এবং Entity ক্লাসে প্রত্যেক কী কলাম আলাদাভাবে সংজ্ঞায়িত থাকে।
- হ্যাশকোড এবং ইকুয়ালস: সঠিকভাবে কম্পোজিট কী ফাংশনাল করতে
hashCodeএবংequalsমেথড ওভাররাইড করতে হবে।
স্প্রিং ওআরএম এর মাধ্যমে Hibernate ব্যবহার করে কম্পোজিট কী পরিচালনা করা সহজ এবং কার্যকর। @EmbeddedId এবং @IdClass দুটি পদ্ধতির মাধ্যমে কম্পোজিট কী কার্যকর করা যায়।
Composite Key এর ধারণা
Composite Key হলো একটি প্রাইমারি কী (Primary Key), যা একাধিক কলামের (fields/attributes) সমন্বয়ে গঠিত। সাধারণত যখন কোনো একক কলাম ডেটাবেস টেবিলে একটি ইউনিক রেকর্ড সনাক্ত করার জন্য যথেষ্ট নয়, তখন Composite Key ব্যবহার করা হয়। এটি একটি ইউনিক পরিচয় নিশ্চিত করতে একাধিক কলামের মান একত্রে ব্যবহার করে।
Composite Key এর প্রয়োজনীয়তা
Composite Key নিম্নলিখিত ক্ষেত্রে ব্যবহার করা হয়:
- ডেটার অখণ্ডতা নিশ্চিত করা: যখন একাধিক কলাম মিলে ইউনিক আইডেন্টিটি তৈরি করে, তখন Composite Key ডেটার সঠিকতা নিশ্চিত করে।
- জটিল সম্পর্ক: অনেক-থেকে-অনেক (Many-to-Many) সম্পর্কের ক্ষেত্রে, একটি মধ্যবর্তী টেবিল (Join Table) তৈরি করতে Composite Key ব্যবহার করা হয়।
- ব্যবসায়িক প্রক্রিয়া: কোনো ডোমেইনে, যেমন লেনদেন বা অর্ডার ম্যানেজমেন্টে, যেখানে একাধিক বৈশিষ্ট্য একত্রে রেকর্ড চিহ্নিত করে।
স্প্রিং ORM এ Composite Key ব্যবহারের উপায়
১. Embeddable Class ব্যবহার করে Composite Key
JPA এবং Hibernate-এ Composite Key তৈরির জন্য @Embeddable এবং @EmbeddedId এনোটেশন ব্যবহার করা হয়।
উদাহরণ:
Embeddable Key ক্লাস তৈরি
@Embeddable
public class OrderId implements Serializable {
private Long orderId;
private Long productId;
// Default Constructor
public OrderId() {}
// Getters and Setters
public Long getOrderId() {
return orderId;
}
public void setOrderId(Long orderId) {
this.orderId = orderId;
}
public Long getProductId() {
return productId;
}
public void setProductId(Long productId) {
this.productId = productId;
}
// hashCode and equals methods
@Override
public int hashCode() {
return Objects.hash(orderId, productId);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
OrderId that = (OrderId) obj;
return Objects.equals(orderId, that.orderId) &&
Objects.equals(productId, that.productId);
}
}
Entity ক্লাসে @EmbeddedId ব্যবহার
@Entity
public class Order {
@EmbeddedId
private OrderId id;
private int quantity;
// Getters and Setters
public OrderId getId() {
return id;
}
public void setId(OrderId id) {
this.id = id;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
২. IdClass ব্যবহার করে Composite Key
Composite Key সংজ্ঞায়িত করতে @IdClass ব্যবহার করা হয়। এই পদ্ধতিতে, একটি সেপারেট ক্লাস Primary Key হিসাবে সংজ্ঞায়িত হয়।
IdClass সংজ্ঞায়িত করা
public class OrderId implements Serializable {
private Long orderId;
private Long productId;
// Default Constructor
public OrderId() {}
// Getters and Setters, hashCode and equals methods
}
Entity ক্লাসে @IdClass ব্যবহার
@Entity
@IdClass(OrderId.class)
public class Order {
@Id
private Long orderId;
@Id
private Long productId;
private int quantity;
// Getters and Setters
}
Composite Key ব্যবহারের সুবিধা
- ডেটার অখণ্ডতা নিশ্চিত: একাধিক কলাম ব্যবহার করে ইউনিক রেকর্ড সনাক্ত করা যায়।
- রিলেশনশিপ মডেলিং সহজ: Many-to-Many সম্পর্কের জন্য মধ্যবর্তী টেবিল তৈরি করা সহজ।
- ডোমেইন মডেলিং: বিভিন্ন ডোমেইনের জটিল সম্পর্ক সহজে মডেল করা যায়।
Composite Key ব্যবহারের সীমাবদ্ধতা
- জটিলতা বৃদ্ধি: একাধিক ফিল্ড ব্যবহারের কারণে কোড এবং ডেটাবেস ডিজাইন জটিল হয়ে যেতে পারে।
- পারফরম্যান্স সমস্যা: Composite Key এর কারণে বড় টেবিলের ক্ষেত্রে পারফরম্যান্সে প্রভাব পড়তে পারে।
স্প্রিং ওআরএম এবং Composite Key এর সংযুক্তি
স্প্রিং ORM JPA এর @EmbeddedId এবং @IdClass এর মাধ্যমে Composite Key পরিচালনার সহজ এবং কার্যকর উপায় প্রদান করে। এটি ডেভেলপারদের ডেটাবেসের জটিল সম্পর্ক সহজে মডেল করতে সাহায্য করে এবং স্প্রিং এর ডেটা অ্যাক্সেস লেয়ারকে আরও শক্তিশালী করে তোলে।
Spring ORM বা Hibernate-এ @Embeddable এবং @EmbeddedId অ্যানোটেশন ব্যবহার করা হয় কম্পোজিট প্রাইমারি কি (Composite Primary Key) পরিচালনার জন্য। যখন কোনো ডাটাবেস টেবিলের জন্য একাধিক কলাম একসঙ্গে প্রাইমারি কি হিসেবে ব্যবহৃত হয়, তখন এই অ্যানোটেশনগুলো কার্যকর ভূমিকা পালন করে।
@Embeddable Annotation
@Embeddable অ্যানোটেশন একটি জাভা ক্লাসকে নির্দেশ করে যে এটি অন্য কোনো Entity-তে এম্বেড করা যাবে। এই ক্লাস সাধারণত কম্পোজিট প্রাইমারি কি বা অন্য কোনো এম্বেডেড ডেটার জন্য ব্যবহৃত হয়।
উদাহরণ:
@Embeddable
public class EmployeeId {
private int departmentId;
private int employeeNumber;
// Getters, Setters, hashCode, and equals মেথড
}
- departmentId এবং employeeNumber একসঙ্গে প্রাইমারি কি হিসেবে ব্যবহৃত হবে।
- @Embeddable অ্যানোটেশনের মাধ্যমে এই ক্লাসকে Entity-তে এম্বেড করা যাবে।
@EmbeddedId Annotation
@EmbeddedId অ্যানোটেশন একটি Entity-তে কম্পোজিট প্রাইমারি কি ব্যবহার করতে সাহায্য করে। এটি @Embeddable দ্বারা নির্ধারিত ক্লাসকে এম্বেড করে।
উদাহরণ:
@Entity
public class Employee {
@EmbeddedId
private EmployeeId id;
private String name;
private String position;
// Getters এবং Setters
}
- Employee Entity-তে @EmbeddedId এর মাধ্যমে EmployeeId ক্লাস এম্বেড করা হয়েছে।
- EmployeeId ক্লাসটি প্রাইমারি কি হিসেবে ব্যবহৃত হবে।
উদাহরণ: সম্পূর্ণ ব্যবহার
১. EmployeeId (Embeddable Class):
@Embeddable
public class EmployeeId {
private int departmentId;
private int employeeNumber;
// Getters, Setters, hashCode, and equals
}
২. Employee (Entity Class):
@Entity
public class Employee {
@EmbeddedId
private EmployeeId id;
private String name;
private String position;
// Getters এবং Setters
}
৩. Repository Interface:
public interface EmployeeRepository extends JpaRepository<Employee, EmployeeId> {
}
৪. ডেটা সংরক্ষণ এবং পুনরুদ্ধার:
@Autowired
private EmployeeRepository employeeRepository;
public void saveEmployee() {
EmployeeId id = new EmployeeId();
id.setDepartmentId(1);
id.setEmployeeNumber(101);
Employee employee = new Employee();
employee.setId(id);
employee.setName("John Doe");
employee.setPosition("Manager");
employeeRepository.save(employee);
}
public Employee findEmployee(int departmentId, int employeeNumber) {
EmployeeId id = new EmployeeId();
id.setDepartmentId(departmentId);
id.setEmployeeNumber(employeeNumber);
return employeeRepository.findById(id).orElse(null);
}
@Embeddable এবং @EmbeddedId-এর সুবিধা
- কম্পোজিট প্রাইমারি কি পরিচালনা: সহজেই একাধিক কলামের সমন্বয়ে প্রাইমারি কি ব্যবহারের সুযোগ দেয়।
- কোড পুনঃব্যবহারযোগ্যতা: এম্বেডেবল ক্লাস পুনরায় ব্যবহারযোগ্য।
- পড়তে এবং পরিচালনা করতে সহজ: জটিল ডেটা স্ট্রাকচার সহজভাবে হ্যান্ডেল করা যায়।
- ORM এর সমর্থন: Hibernate এবং JPA উভয়েই এই অ্যানোটেশনগুলো কার্যকরভাবে সমর্থন করে।
Spring ORM-এ @Embeddable এবং @EmbeddedId অ্যানোটেশন জটিল ডেটাবেস স্ট্রাকচার যেমন কম্পোজিট প্রাইমারি কি ব্যবস্থাপনার জন্য অপরিহার্য। এগুলোর মাধ্যমে জটিলতা হ্রাস পায় এবং কোড স্ট্রাকচার আরও পরিষ্কার হয়।
Composite Key হলো একটি ডেটাবেস টেবিলের জন্য একাধিক কলামের সমন্বয়ে তৈরি প্রাইমারি কী (Primary Key)। এটি তখন ব্যবহার করা হয় যখন একটি মাত্র কলাম প্রাইমারি কী হিসেবে যথেষ্ট নয়। স্প্রিং ORM-এ JPA (Java Persistence API) ব্যবহার করে সহজেই Composite Keys পরিচালনা করা যায়।
Composite Key তৈরির ধাপ
- Embeddable Class ব্যবহার করে Composite Key নির্ধারণ।
- Entity Class এ Embeddable Class-কে Primary Key হিসেবে সংযুক্ত করা।
উদাহরণ: Composite Keys এর ব্যবহার
ধাপ ১: Embeddable Class তৈরি করা
import jakarta.persistence.Embeddable;
import java.io.Serializable;
@Embeddable
public class EmployeeId implements Serializable {
private int departmentId;
private int employeeNumber;
// Default Constructor
public EmployeeId() {}
// Parameterized Constructor
public EmployeeId(int departmentId, int employeeNumber) {
this.departmentId = departmentId;
this.employeeNumber = employeeNumber;
}
// Getters and Setters
public int getDepartmentId() {
return departmentId;
}
public void setDepartmentId(int departmentId) {
this.departmentId = departmentId;
}
public int getEmployeeNumber() {
return employeeNumber;
}
public void setEmployeeNumber(int employeeNumber) {
this.employeeNumber = employeeNumber;
}
// Override equals() and hashCode() methods
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EmployeeId that = (EmployeeId) o;
return departmentId == that.departmentId && employeeNumber == that.employeeNumber;
}
@Override
public int hashCode() {
return Objects.hash(departmentId, employeeNumber);
}
}
ব্যাখ্যা:
- @Embeddable অ্যানোটেশনটি দিয়ে এই ক্লাসটিকে এমবেডযোগ্য হিসেবে চিহ্নিত করা হয়েছে।
- Serializable ইন্টারফেস ইমপ্লিমেন্ট করা প্রয়োজন কারণ JPA এই ক্লাসকে ডেটাবেসে সংরক্ষণযোগ্য হিসেবে বিবেচনা করে।
- equals() এবং hashCode() মেথড ওভাররাইড করা আবশ্যক।
ধাপ ২: Entity Class এ Composite Key ব্যবহার
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
@Entity
@IdClass(EmployeeId.class)
public class Employee {
@Id
private int departmentId;
@Id
private int employeeNumber;
private String name;
private String position;
// Default Constructor
public Employee() {}
// Parameterized Constructor
public Employee(int departmentId, int employeeNumber, String name, String position) {
this.departmentId = departmentId;
this.employeeNumber = employeeNumber;
this.name = name;
this.position = position;
}
// Getters and Setters
public int getDepartmentId() {
return departmentId;
}
public void setDepartmentId(int departmentId) {
this.departmentId = departmentId;
}
public int getEmployeeNumber() {
return employeeNumber;
}
public void setEmployeeNumber(int employeeNumber) {
this.employeeNumber = employeeNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
}
ব্যাখ্যা:
- @IdClass(EmployeeId.class): এটি নির্দেশ করে যে
Employeeটেবিলের প্রাইমারি কী EmployeeId ক্লাসের সাথে ম্যাপ করা হয়েছে। - @Id: এই অ্যানোটেশনটি Composite Key এর প্রতিটি অংশের জন্য প্রয়োগ করতে হয়।
ধাপ ৩: Repository তৈরি করা
import org.springframework.data.jpa.repository.JpaRepository;
public interface EmployeeRepository extends JpaRepository<Employee, EmployeeId> {
}
ব্যাখ্যা:
- JpaRepository-তে
EmployeeIdকে Key Type হিসেবে ব্যবহার করা হয়েছে। - Spring Data JPA স্বয়ংক্রিয়ভাবে Composite Key এর জন্য ডেটা অ্যাক্সেস মেথড তৈরি করে।
ধাপ ৪: সার্ভিস লেয়ারে ব্যবহার
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
public void saveEmployee(Employee employee) {
employeeRepository.save(employee);
}
public Employee getEmployeeById(EmployeeId employeeId) {
return employeeRepository.findById(employeeId).orElse(null);
}
}
ব্যাখ্যা:
- saveEmployee(): একটি নতুন এমপ্লয়ি ডেটাবেসে সংরক্ষণ করে।
- getEmployeeById(): Composite Key এর মাধ্যমে একটি এমপ্লয়ি রিট্রিভ করে।
উদাহরণ: ডেটা সংরক্ষণ এবং রিট্রিভ করা
ডেটা সংরক্ষণ
EmployeeId employeeId = new EmployeeId(1, 101);
Employee employee = new Employee(1, 101, "John Doe", "Developer");
employeeService.saveEmployee(employee);
ডেটা রিট্রিভ
EmployeeId employeeId = new EmployeeId(1, 101);
Employee employee = employeeService.getEmployeeById(employeeId);
System.out.println("Employee Name: " + employee.getName());
Composite Key ব্যবহারের সুবিধা
- ডেটার ইন্টিগ্রিটি নিশ্চিত: একাধিক কলামের সমন্বয়ে ডেটার অনন্যতা নিশ্চিত করা যায়।
- স্পষ্ট রিলেশনশিপ: ডেটাবেস টেবিলগুলোর মধ্যে জটিল সম্পর্ক সহজে পরিচালনা করা যায়।
- পুনরায় ব্যবহারযোগ্যতা: @Embeddable ক্লাস পুনরায় ব্যবহারযোগ্য যা কোড মডুলার এবং পরিচ্ছন্ন করে।
Read more