Trang chủHướng dẫnKhám phá sức mạnh của @Repository Annotation trong Spring
Java

Khám phá sức mạnh của @Repository Annotation trong Spring

CyStack blog 4 phút để đọc
CyStack blog03/10/2025
Locker Avatar

Chris Pham

Technical Writer

Locker logo social
Reading Time: 4 minutes

Annotation @Repository đóng vai trò quan trọng trong việc định nghĩa các lớp chịu trách nhiệm cung cấp cơ chế lưu trữ, truy xuất, tìm kiếm, cập nhật và xóa đối tượng (hay còn gọi là các hoạt động CRUD – Create, Read, Update, Delete).

@Repository Annotation trong Spring

Nó giúp chúng ta tách biệt hoàn toàn logic truy cập dữ liệu khỏi các tầng nghiệp vụ (business logic), đảm bảo kiến trúc ứng dụng sạch sẽ và dễ bảo trì.

Việc hiểu và sử dụng đúng @Repository không chỉ cải thiện cấu trúc code mà còn giúp Spring Framework quản lý ngoại lệ và giao dịch một cách hiệu quả hơn.

@Repository Annotation là gì

Về cơ bản, @Repository annotation là một chuyên biệt hóa của @Component annotation trong Spring Framework. Điều này có nghĩa là bất kỳ lớp nào bạn đánh dấu bằng @Repository đều trở thành một Spring Bean và được Spring Container tự động phát hiện thông qua cơ chế quét classpath (classpath scanning).

Lớp Repository mang ý nghĩa rất gần với mẫu thiết kế DAO (Data Access Object) quen thuộc, nơi các lớp DAO chịu trách nhiệm cung cấp các hoạt động CRUD trên các bảng cơ sở dữ liệu. Nó đóng vai trò như một cầu nối giữa tầng nghiệp vụ và tầng lưu trữ dữ liệu.

Tuy nhiên, điều quan trọng cần lưu ý là nếu bạn đang sử dụng Spring Data (như Spring Data JPA) để quản lý các thao tác cơ sở dữ liệu, bạn nên ưu tiên sử dụng các interface Repository được cung cấp bởi Spring Data thay vì tự triển khai một lớp @Repository thủ công.

Spring Data cung cấp rất nhiều tiện ích giúp chúng ta giảm thiểu đáng kể lượng code boilerplate, tự động tạo ra các phương thức truy vấn dựa trên tên phương thức mà không cần viết implement.

Ví dụ về Spring Repository

Đầu tiên, chúng ta tạo một dự án Maven cơ bản trong Eclipse hoặc bất kỳ IDE nào bạn quen dùng. Sau đó, bạn cần thêm dependency spring-context vào file pom.xml của mình.

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.0.6.RELEASE</version>
</dependency>

@Repository Annotation trong Spring

Tiếp theo, chúng ta định nghĩa lớp Employee model class mà chúng ta muốn tạo repository cho nó. Lớp này đơn giản chứa các thuộc tính id, name, jobTitle cùng với các constructor, getter, setter và phương thức toString().

package com.journaldev.spring.model;

public class Employee {

	private int id;
	private String name;
	private String jobTitle;

	public Employee() {
	}

	public Employee(int i, String n, String jt) {
		this.id = i;
		this.name = n;
		this.jobTitle = jt;
	}

	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;
	}

	public String getJobTitle() {
		return jobTitle;
	}

	public void setJobTitle(String jobTitle) {
		this.jobTitle = jobTitle;
	}

	@Override
	public String toString() {
		return id + "," + name + "," + jobTitle;
	}
}

Trước khi triển khai lớp Repository, tôi đã tạo một interface ObjectRepository tổng quát sử dụng Generics. Interface này định nghĩa các contract về các thao tác CRUD mà lớp repository của chúng ta sẽ phải triển khai.

ObjectRepository

package com.journaldev.spring.repository;

public interface ObjectRepository<T> {

	public void store(T t);

	public T retrieve(int id);

	public T search(String name);

	public T delete(int id);
}

Việc sử dụng Generics ở đây là một kỹ thuật mạnh mẽ, giúp chúng ta tạo ra một contract lỏng lẻo, dễ dàng tái sử dụng cho nhiều loại đối tượng khác nhau. Giờ đây, chúng ta hãy cùng xem cách triển khai lớp Repository chính, EmployeeRepository, sử dụng @Repository annotation.

package com.journaldev.spring.repository;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Repository;

import com.journaldev.spring.model.Employee;

@Repository
public class EmployeeRepository implements ObjectRepository<Employee> {

	private Map<Integer, Employee> repository;

	public EmployeeRepository() {
		this.repository = new HashMap<>();
	}

	@Override
	public void store(Employee emp) {
		repository.put(emp.getId(), emp);
	}

	@Override
	public Employee retrieve(int id) {
		return repository.get(id);
	}

	@Override
	public Employee search(String name) {
		Collection<Employee> emps = repository.values();
		for (Employee emp : emps) {
			if (emp.getName().equalsIgnoreCase(name))
				return emp;
		}
		return null;
	}

	@Override
	public Employee delete(int id) {
		Employee e = repository.get(id);
		this.repository.remove(id);
		return e;
	}

}

Lưu ý rằng tôi đang sử dụng một Map (cụ thể là HashMap) trong bộ nhớ để lưu trữ dữ liệu đối tượng Employee. Trong các ứng dụng thực tế, bạn sẽ thay thế Map này bằng cơ chế lưu trữ bền vững hơn như cơ sở dữ liệu (sử dụng JDBC, JPA/Hibernate), file, hoặc một dịch vụ bên ngoài.

Kiểm tra Spring Repository

Repository của chúng ta đã sẵn sàng. Bây giờ, chúng ta sẽ tạo một lớp main để kiểm tra các chức năng đã triển khai.

package com.journaldev.spring;

import java.sql.SQLException;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.journaldev.spring.model.Employee;
import com.journaldev.spring.repository.EmployeeRepository;

public class SpringMainClass {

	public static void main(String[] args) throws SQLException {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		context.scan("com.journaldev.spring");
		context.refresh();

		EmployeeRepository repository = context.getBean(EmployeeRepository.class);

		// store
		repository.store(new Employee(1, "Pankaj", "CEO"));
		repository.store(new Employee(2, "Anupam", "Editor"));
		repository.store(new Employee(3, "Meghna", "CFO"));

		// retrieve
		Employee emp = repository.retrieve(1);
		System.out.println(emp);

		// search
		Employee cfo = repository.search("Meghna");
		System.out.println(cfo);

		// delete
		Employee editor = repository.delete(2);
		System.out.println(editor);

		// close the spring context
		context.close();
	}

}

Trong lớp SpringMainClass, chúng ta khởi tạo AnnotationConfigApplicationContext, chỉ định package cần quét (com.journaldev.spring) để Spring Container có thể tìm và khởi tạo các bean, bao gồm cả EmployeeRepository của chúng ta. Sau đó, chúng ta gọi context.refresh() để hoàn tất quá trình cấu hình.

Chúng ta sử dụng context.getBean(EmployeeRepository.class) để lấy thể hiện của EmployeeRepository đã được Spring quản lý, rồi thực hiện các thao tác store, retrieve, search, và delete để kiểm tra chức năng. Cuối cùng, chúng ta in kết quả ra console để xác nhận. Đừng quên gọi context.close() để đóng Spring context khi ứng dụng kết thúc, giải phóng tài nguyên.

Khi bạn chạy lớp này như một ứng dụng Java thông thường, bạn sẽ nhận được kết quả như sau:

1,Pankaj,CEO
3,Meghna,CFO
2,Anupam,Editor

Kết luận

Qua bài viết này, chúng ta đã cùng nhau khám phá sâu hơn về @Repository annotation trong Spring Framework. Việc sử dụng @Repository không chỉ giúp chúng ta tổ chức code một cách rõ ràng theo nguyên tắc tách biệt mối quan tâm (Separation of Concerns) mà còn tận dụng được các tính năng tiện lợi của Spring như xử lý ngoại lệ tự động.

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất