Cấu hình Spring Data JPA với @EnableJpaRepositories annotation

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

Trong bài viết Tổng quan về Spring Data JPA, mình đã giới thiệu với các bạn Spring Data JPA và cách cấu hình nó sử dụng tập tin XML. Có một cách khác để cấu hình Spring Data JPA đó là sử dụng các annotation mà nó hỗ trợ như @EnableJpaRepositories annotation. Cụ thể như thế nào? Chúng ta hãy cùng nhau tìm hiểu trong bài viết này các bạn nhé!

Đầu tiên, mình sẽ tạo mới một Maven project để làm ví dụ:

Chúng ta sẽ sử dụng Java 11 cho project này:

<properties>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
</properties>
Spring Data JPA và Hibernate implementation dependencies như sau:

Mình sẽ sử dụng MySQL database để làm ví dụ:

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>

Và Project Lombok nữa:

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>

Để làm ví dụ và để đơn giản, mình định nghĩa 1 table trong database chứa thông tin sinh viên với 2 cột như sau:

CREATE TABLE `student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

Entity của table này:

package com.huongdanjava.springdatajpa.entity;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Getter;
import lombok.Setter;

@Table(name = "student")
@Entity
@Getter
@Setter
public class Student implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue
private Long id;

@Column
private String name;
}

và Repository class cho nó nữa:

package com.huongdanjava.springdatajpa.repositories;

import org.springframework.data.jpa.repository.JpaRepository;
import com.huongdanjava.springdatajpa.entity.Student;

public interface StudentRepository extends JpaRepository<Student, Long> {

}

Bây giờ, mình sẽ tạo mới một class để cấu hình cho phần thao tác với database của ứng dụng sử dụng các class Repository của Spring Data JPA với annotation @EnableJpaRepositories như sau:

package com.huongdanjava.springdatajpa;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@EnableJpaRepositories(basePackages = {"com.huongdanjava.springdatajpa.repositories"})
public class DatabaseConfiguration {

}

Spring khi scan và gặp annotation @EnableJpaRepositories này sẽ tự động khởi tạo các đối tượng cần thiết để chúng ta có thể sử dụng các Repository của Spring Data JPA.

  Sử dụng EclipseLink thay thế Hibernate trong Spring Data JPA Starter
  Authentication trong Spring Security

Xem thêm tuyển dụng Spring hấp dẫn trên TopDev

Thuộc tính basePackages sẽ định nghĩa package mà chúng ta đã định nghĩa các Repository. Có 2 thuộc tính khác của annotation @EnableJpaRepositories mà chúng ta cần cấu hình nữa là entityManagerFactoryRef và transactionManagerRef. Giá trị của những thuộc tính này là tên bean được tạo trong Spring container, lần lượt là của EntityManagerFactory và TransactionManager. Giá trị mặc định của 2 thuộc tính này lần lượt là entityManagerFactory và transactionManager.

Cho EntityManagerFactory, các bạn sử dụng implementation là class LocalContainerEntityManagerFactoryBean như mình như sau:

@Bean
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factory.setPackagesToScan("com.huongdanjava.springdatajpa.entity");
factory.setDataSource(dataSource());
factory.afterPropertiesSet();

return factory.getObject();
}

Phương thức setPackagesToScan() khai báo package sẽ chứa các JPA entity của ứng dụng. Trong ví dụ của mình thì đó là package com.huongdanjava.springdatajpa.entity.

Phương thức setDataSource() sẽ cấu hình thông tin DataSource connect tới database, các bạn có thể khai báo một bean của DataSource với implementation là class DriverManagerDataSource như sau:

@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/jpa_example");
dataSource.setUsername("root");
dataSource.setPassword("123456");

return dataS

Các thông tin database trong cấu hình của DataSource các bạn nên lấy từ tập tin properties. Ở đây, để đơn giản nên mình hardcode những thông tin này các bạn nhé.

Bean cho TransactionManager, các bạn có thể khai báo như sau:

@Bean
public TransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource());

return transactionManager;
}

Đến đây thì chúng ta đã cấu hình xong Spring Data JPA cho ứng dụng của mình.

Để kiểm tra kết quả, mình sẽ viết một class với main() method có nội dung như sau:

package com.huongdanjava.springdatajpa;

import java.util.Optional;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.huongdanjava.springdatajpa.entity.Student;
import com.huongdanjava.springdatajpa.repositories.StudentRepository;

public class Application {

public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(DatabaseConfiguration.class);

StudentRepository helloRepository = (StudentRepository) ac.getBean("studentRepository");
Optional<Student> student = helloRepository.findById(1L);

System.out.println(student.get().getName());
}

}

Giả sử trong database, mình đang có những thông tin như sau:

thì kết quả khi chạy ứng dụng sẽ như sau: