Spring Data JPA কী?

Spring Data JPA হলো Spring Framework-এর একটি গুরুত্বপূর্ণ মডিউল যা Java Persistence API (JPA)-এর উপর ভিত্তি করে তৈরি। এটি ডেভেলপারদের ডেটাবেজ অপারেশন সহজ ও দ্রুততর করে তোলে। Spring Data JPA ব্যবহার করে আপনি খুব কম কোড লিখেই CRUD (Create, Read, Update, Delete) অপারেশন করতে পারেন।


কেন Spring Data JPA ব্যবহার করবেন?

ঐতিহ্যগতভাবে JDBC বা হাতে লেখা JPA কোডে অনেক বয়লারপ্লেট কোড লিখতে হতো। Spring Data JPA এই সমস্যার সমাধান করে:

  • কম কোড: Repository ইন্টারফেস ব্যবহার করে স্বয়ংক্রিয়ভাবে SQL Query তৈরি হয়
  • সহজ কনফিগারেশন: মিনিমাল কনফিগারেশনেই কাজ শুরু করা যায়
  • Pagination ও Sorting: বিল্ট-ইন সাপোর্ট পাওয়া যায়
  • Custom Query: প্রয়োজনে নিজের Query লেখার সুবিধা আছে
  • Transaction Management: স্বয়ংক্রিয় ট্রানজেকশন ম্যানেজমেন্ট

প্রয়োজনীয় Dependency

pom.xml ফাইলে নিচের dependency যোগ করুন:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

Entity ক্লাস তৈরি

Entity ক্লাস হলো ডেটাবেজ টেবিলের Java রিপ্রেজেন্টেশন। @Entity অ্যানোটেশন দিয়ে একটি ক্লাসকে Entity হিসেবে চিহ্নিত করা হয়।

import jakarta.persistence.*;

@Entity
@Table(name = "students")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;

    @Column(name = "email", unique = true)
    private String email;

    @Column(name = "age")
    private int age;

    // Constructors
    public Student() {}

    public Student(String name, String email, int age) {
        this.name = name;
        this.email = email;
        this.age = age;
    }

    // Getters and Setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}

গুরুত্বপূর্ণ Annotation সমূহ:

  • @Entity — ক্লাসটি একটি JPA Entity তা নির্দেশ করে
  • @Table — ডেটাবেজে টেবিলের নাম নির্দিষ্ট করে
  • @Id — Primary Key চিহ্নিত করে
  • @GeneratedValue — Primary Key স্বয়ংক্রিয়ভাবে জেনারেট হবে
  • @Column — কলামের বিস্তারিত কনফিগারেশন দেয়

Repository ইন্টারফেস

Spring Data JPA-এর সবচেয়ে শক্তিশালী ফিচার হলো Repository। JpaRepository ইন্টারফেস extend করলেই বেসিক CRUD মেথড পাওয়া যায়।

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {

    // নাম দিয়ে স্টুডেন্ট খুঁজবে
    List<Student> findByName(String name);

    // ইমেইল দিয়ে স্টুডেন্ট খুঁজবে
    Optional<Student> findByEmail(String email);

    // বয়সের চেয়ে বড় স্টুডেন্টদের খুঁজবে
    List<Student> findByAgeGreaterThan(int age);

    // নাম এবং বয়স দিয়ে খুঁজবে
    List<Student> findByNameAndAge(String name, int age);
}

JpaRepository<Student, Long> — এখানে Student হলো Entity টাইপ এবং Long হলো Primary Key-এর টাইপ।


Service Layer

Business logic আলাদা রাখতে Service Layer তৈরি করুন:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;

@Service
public class StudentService {

    @Autowired
    private StudentRepository studentRepository;

    // নতুন স্টুডেন্ট সেভ করা
    public Student saveStudent(Student student) {
        return studentRepository.save(student);
    }

    // সব স্টুডেন্ট দেখা
    public List<Student> getAllStudents() {
        return studentRepository.findAll();
    }

    // ID দিয়ে স্টুডেন্ট খোঁজা
    public Optional<Student> getStudentById(Long id) {
        return studentRepository.findById(id);
    }

    // স্টুডেন্ট আপডেট করা
    public Student updateStudent(Long id, Student updatedStudent) {
        Student student = studentRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Student not found with id: " + id));
        student.setName(updatedStudent.getName());
        student.setEmail(updatedStudent.getEmail());
        student.setAge(updatedStudent.getAge());
        return studentRepository.save(student);
    }

    // স্টুডেন্ট মুছে ফেলা
    public void deleteStudent(Long id) {
        studentRepository.deleteById(id);
    }

    // নাম দিয়ে খোঁজা
    public List<Student> findByName(String name) {
        return studentRepository.findByName(name);
    }
}

Controller Layer

REST API তৈরির জন্য Controller:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/api/students")
public class StudentController {

    @Autowired
    private StudentService studentService;

    // POST: নতুন স্টুডেন্ট তৈরি
    @PostMapping
    public ResponseEntity<Student> createStudent(@RequestBody Student student) {
        Student savedStudent = studentService.saveStudent(student);
        return ResponseEntity.ok(savedStudent);
    }

    // GET: সব স্টুডেন্ট
    @GetMapping
    public ResponseEntity<List<Student>> getAllStudents() {
        return ResponseEntity.ok(studentService.getAllStudents());
    }

    // GET: ID দিয়ে
    @GetMapping("/{id}")
    public ResponseEntity<Student> getStudentById(@PathVariable Long id) {
        return studentService.getStudentById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    // PUT: আপডেট
    @PutMapping("/{id}")
    public ResponseEntity<Student> updateStudent(@PathVariable Long id,
                                                  @RequestBody Student student) {
        return ResponseEntity.ok(studentService.updateStudent(id, student));
    }

    // DELETE: মুছে ফেলা
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteStudent(@PathVariable Long id) {
        studentService.deleteStudent(id);
        return ResponseEntity.noContent().build();
    }
}

Custom Query — @Query Annotation

যখন Method Naming দিয়ে জটিল Query করা সম্ভব হয় না, তখন @Query ব্যবহার করুন:

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {

    // JPQL Query
    @Query("SELECT s FROM Student s WHERE s.age BETWEEN :minAge AND :maxAge")
    List<Student> findStudentsByAgeRange(@Param("minAge") int minAge,
                                          @Param("maxAge") int maxAge);

    // Native SQL Query
    @Query(value = "SELECT * FROM students WHERE name LIKE %:keyword%",
           nativeQuery = true)
    List<Student> searchByNameKeyword(@Param("keyword") String keyword);

    // Update Query
    @Modifying
    @Transactional
    @Query("UPDATE Student s SET s.age = :age WHERE s.id = :id")
    int updateStudentAge(@Param("id") Long id, @Param("age") int age);
}

Pagination এবং Sorting

বড় ডেটাসেটের জন্য Pagination অত্যন্ত গুরুত্বপূর্ণ:

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

@Service
public class StudentService {

    // Pagination সহ সব স্টুডেন্ট
    public Page<Student> getStudentsByPage(int pageNumber, int pageSize) {
        Pageable pageable = PageRequest.of(pageNumber, pageSize);
        return studentRepository.findAll(pageable);
    }

    // Sorting সহ
    public List<Student> getStudentsSortedByName() {
        Sort sort = Sort.by(Sort.Direction.ASC, "name");
        return studentRepository.findAll(sort);
    }

    // Pagination + Sorting একসাথে
    public Page<Student> getStudentsWithPaginationAndSorting(int page, int size) {
        Pageable pageable = PageRequest.of(page, size,
                Sort.by("name").ascending());
        return studentRepository.findAll(pageable);
    }
}

application.properties কনফিগারেশন

# Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/studentdb
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# JPA/Hibernate Configuration
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

ddl-auto এর বিভিন্ন মান:

  • create — প্রতিবার নতুন টেবিল তৈরি করে (পুরনো ডেটা মুছে যায়)
  • create-drop — অ্যাপ বন্ধ হলে টেবিল মুছে ফেলে
  • update — পরিবর্তন হলে স্কিমা আপডেট করে (ডেটা থাকে)
  • validate — স্কিমা যাচাই করে কিন্তু পরিবর্তন করে না
  • none — কোনো অ্যাকশন নেয় না

Entity Relationship — One-to-Many

@Entity
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToMany(mappedBy = "department", cascade = CascadeType.ALL)
    private List<Student> students;
}

@Entity
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToOne
    @JoinColumn(name = "department_id")
    private Department department;
}

সংক্ষেপে মূল বিষয়গুলো

বিষয় বিবরণ
@Entity ক্লাসকে ডেটাবেজ টেবিল হিসেবে চিহ্নিত করে
@Repository ডেটা অ্যাক্সেস লেয়ার নির্দেশ করে
JpaRepository CRUD মেথড স্বয়ংক্রিয়ভাবে দেয়
@Query কাস্টম JPQL বা Native Query লেখার সুবিধা
Pageable Pagination ও Sorting সাপোর্ট করে
@Transactional ট্রানজেকশন ম্যানেজমেন্ট নিশ্চিত করে

উপসংহার

Spring Data JPA Java ডেভেলপারদের জন্য ডেটাবেজ অপারেশনকে অনেক সহজ করে দিয়েছে। বয়লারপ্লেট কোড কমিয়ে, এটি ডেভেলপমেন্টকে দ্রুত ও কার্যকর করে তোলে। একবার Entity, Repository, Service এবং Controller এর স্তরগুলো বুঝতে পারলে, যেকোনো জটিল অ্যাপ্লিকেশনও সহজে তৈরি করা সম্ভব।

Spring Boot প্রজেক্টে Spring Data JPA যোগ করা অত্যন্ত সহজ এবং এটি প্রোডাকশন-গ্রেড অ্যাপ্লিকেশন তৈরিতে অপরিহার্য একটি টুল।

Share