Tổng Quan Về Spring Data JPA - Hướng Dẫn Java
Có thể bạn quan tâm
Trong bài viết trước, mình đã giới thiệu với các bạn tổng quan về JPA Query Language để thao tác với các loại database sử dụng các entity. Mỗi khi các bạn cần thông tin gì từ database, các bạn sẽ sử dụng các câu lệnh SELECT hoặc UPDATE hoặc DELETE cùng với tên entity để build thành câu query, sau đó sẽ lấy đối tượng Query từ Entity Manager sử dụng câu query này, và cuối cùng là gọi một phương thức thích hợp tuỳ theo nhu cầu của các bạn từ đối tượng Query này để lấy kết quả mà các bạn mong muốn. Rất nhiều bước cần phải làm phải không các bạn? Nếu các bạn sử dụng JPA cùng với Spring framework trong dự án của mình thì hãy thử sử dụng Spring Data JPA nhé! Nó sẽ giúp các bạn giảm thiểu các công việc phải làm trong một số trường hợp. Cụ thể như thế nào? Trong bài viết này, chúng ta hãy cùng nhau tìm hiểu về Spring Data JPA 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 17 cho ví dụ này:
Java <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties>| 1234 | <properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties> |
Spring Data JPA dependency:
XHTML <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>3.1.1</version> </dependency>| 12345 | <dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-jpa</artifactId><version>3.1.1</version></dependency> |
Ở đây, mình sẽ sử dụng JPA với implementation của Hibernate nên mình sẽ thêm Hibernate dependency như sau:
XHTML <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.2.6.Final</version> </dependency>| 12345 | <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>6.2.6.Final</version></dependency> |
Project Lombok:
XHTML <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.28</version> <scope>provided</scope> </dependency>| 123456 | <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version><scope>provided</scope></dependency> |
Trong bài viết này, mình sẽ sử dụng MySQL database:
XHTML <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>| 12345 | <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency> |
Để đơn giản, mình chỉ định nghĩa 1 table chứa thông tin sinh viên với 2 cột như sau:
MySQL 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;| 12345 | CREATETABLE`student`(`id`bigint(20)NOT NULLAUTO_INCREMENT,`name`varchar(50)DEFAULTNULL,PRIMARY KEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=latin1; |
Entity của table này:
Java package com.huongdanjava.springdatajpa; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.Table; import java.io.Serializable; 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; }| 123456789101112131415161718192021222324252627 | packagecom.huongdanjava.springdatajpa; importjakarta.persistence.Column;importjakarta.persistence.Entity;importjakarta.persistence.GeneratedValue;importjakarta.persistence.Id;importjakarta.persistence.Table;importjava.io.Serializable; importlombok.Getter;importlombok.Setter; @Table(name="student")@Entity@Getter@SetterpublicclassStudentimplementsSerializable{ privatestaticfinallongserialVersionUID=1L; @Id@GeneratedValueprivateLongid; @ColumnprivateStringname;} |
Để làm việc với JPA, chúng ta cần có một tập tin cấu hình persistence.xml cho nó. Các bạn hãy tạo mới tập tin persistence.xml nằm trong thư mục /src/main/resources/META-INF các bạn nhé!
Nội dung của tập tin này như sau:
XHTML <?xml version="1.0" encoding="UTF-8" standalone="no"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="springdataPU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <class>com.huongdanjava.springdatajpa.Student</class> <exclude-unlisted-classes/> <properties> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="false"/> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <property name="hibernate.connection.driver_class" value="com.mysql.cj.jdbc.Driver"/> <property name="javax.persistence.validation.mode" value="none"/> </properties> </persistence-unit> </persistence>| 123456789101112131415161718 | <?xml version="1.0"encoding="UTF-8"standalone="no"?><persistence version="2.1"xmlns="http://xmlns.jcp.org/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"><persistence-unit name="springdataPU"transaction-type="RESOURCE_LOCAL"><provider>org.hibernate.jpa.HibernatePersistenceProvider</provider><class>com.huongdanjava.springdatajpa.Student</class><exclude-unlisted-classes/><properties><property name="hibernate.show_sql"value="true"/><property name="hibernate.format_sql"value="false"/><property name="hibernate.dialect"value="org.hibernate.dialect.MySQLDialect"/><property name="hibernate.connection.driver_class"value="com.mysql.cj.jdbc.Driver"/><property name="javax.persistence.validation.mode"value="none"/></properties></persistence-unit></persistence> |
Khai báo EntityManagerFactory trong Spring container:
XHTML <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="persistenceUnitName" value="springdataPU" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> </bean>| 1234567 | <bean id="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="dataSource"ref="dataSource" /><property name="persistenceUnitName"value="springdataPU" /><property name="jpaVendorAdapter"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /></property></bean> |
với datasource:
XHTML <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/jpa_example" /> <property name="username" value="root" /> <property name="password" value="123456" /> </bean>| 123456 | <bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName"value="com.mysql.cj.jdbc.Driver" /><property name="url"value="jdbc:mysql://localhost:3306/jpa_example" /><property name="username"value="root" /><property name="password"value="123456" /></bean> |
OK, vậy là đã chuẩn bị mọi thứ xong rồi đó các bạn:

Các bạn có thể tham khảo thêm bài viết về JPA và Spring framework tại đây nhé!
Giờ chúng ta đi vào chủ đề chính của bài viết này thôi.
Điều đầu tiên, các bạn cần phải biết là Spring Data JPA là một module nhỏ trong một project lớn gọi là Spring Data project. Mục đích của Spring Data project là giảm thiểu các đoạn code lặp đi lặp lại liên quan đến phần thao tác với các hệ thống quản trị data khi phát triển các ứng dụng có sử dụng Spring framework. Ngoài Spring Data JPA hỗ trợ cho JPA giảm thiểu code để truy cập và thao tác với các hệ thống quản trị cơ cở dữ liệu, chúng ta còn có Spring Data JDBC (cũng giống như Spring Data JPA), Spring Data LDAP (hỗ trợ Spring LDAP), Spring Data MongoDB (hỗ trợ cho MongoDB),… Các bạn có thể tìm thấy đầy đủ các module của Spring Data tại đây.
Để đạt được mục đích giảm thiểu code như mình đã nói, Spring Data định nghĩa một interface chính tên là Repository nằm trong module Spring Data Common, module này sẽ được sử dụng cho tất cả các module còn lại trong Spring Data project. Nội dung của interface này đơn giản như sau:
Java package org.springframework.data.repository; import org.springframework.stereotype.Indexed; @Indexed public interface Repository<T, ID> { }| 12345678 | packageorg.springframework.data.repository; importorg.springframework.stereotype.Indexed; @IndexedpublicinterfaceRepository<T,ID>{ } |
Interface này sử dụng 2 generic type:
- T là domain class mà repository sẽ quản lý
- ID là kiểu dữ liệu của ID của domain class mà repository quản lý.
Vì interface này đơn giản như vậy nên chắc chắn nó phải có những interface khác extend nó để thể hiện Spring Data project làm được những gì phải không các bạn? 😀
Ở đây, chúng ta sẽ có nhiều interface khác extend từ interface repository tuỳ thuộc vào module mà chúng ta sử dụng nhưng do chúng ta đang thảo luận về Spring Data JPA nên mình sẽ chỉ liệt kê ở đây một interface duy nhất extend interface Repository mà Spring Data JPA đang sử dụng. Đó chính là interface CrudRepository.
Interface CrudRepository với ý nghĩa create, read, update, delete cho phép chúng ta thực hiện các thao tác cơ bản đến với các hệ thống data, hệ thống data ở đây các bạn phải hiểu theo nghĩa rộng nghĩa là nó không chỉ là database đâu nhé các bạn.
Để hỗ trợ việc phân trang và sắp xếp cho Spring Data JPA, chúng ta còn phải nói đến một interface khác là PagingAndSortingRepository.
Tất cả các interface mà mình vừa kể trên đều nằm trong module Spring Data Common nhé các bạn.
Trong Spring Data JPA, ở đây, chúng ta chỉ có duy nhất một interface là JpaRepository kế thừa interface PagingAndSortingRepository. Với việc extend từ interface PagingAndSortingRepository, các bạn cũng có thể hình dung là Spring Data JPA có thể giúp chúng ta giảm thiểu code cho các thao tác nào liên quan đến database rồi phải không các bạn? Có thể kể ra đây là: create, read, update, delete, paging và sort. 😀
Các bạn có thể thấy rõ cấu trúc extend cho những interface trên bằng hình ảnh sau:

OK, vậy giờ hãy cùng mình làm một ví dụ với interface JpaRepository xem nó hoạt động như thế nào nhé các bạn.
Bây giờ mình sẽ tạo mới một interface tên là HelloRepository extend từ Jpa Repository với nội dung như sau:
Java package com.huongdanjava.springdatajpa; import org.springframework.data.jpa.repository.JpaRepository; public interface HelloRepository extends JpaRepository<Student, Long> { }| 1234567 | packagecom.huongdanjava.springdatajpa; importorg.springframework.data.jpa.repository.JpaRepository; publicinterfaceHelloRepository extendsJpaRepository<Student,Long>{ } |
Domain class ở đây chính là tên entity Student còn Long chính là kiểu dữ liệu của properties trong entity Student mapping với column primary key trong table student nha các bạn.
Giờ chúng ta sẽ khai báo interface này trong Spring container như sau:
XHTML <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <jpa:repositories base-package="com.huongdanjava.springdatajpa"/> <context:annotation-config/> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="persistenceUnitName" value="springdataPU"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/jpa_example"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> </beans>| 1234567891011121314151617181920212223242526272829 | <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:jpa="http://www.springframework.org/schema/data/jpa"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <jpa:repositories base-package="com.huongdanjava.springdatajpa"/> <context:annotation-config/> <bean id="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="dataSource"ref="dataSource"/><property name="persistenceUnitName"value="springdataPU"/><property name="jpaVendorAdapter"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/></property></bean> <bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName"value="com.mysql.cj.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/jpa_example"/><property name="username"value="root"/><property name="password"value="123456"/></bean> </beans> |
Ở đây, mình sử dụng namespace jpa:repositories với base package là com.huongdanjava.springdatajpa để scan HelloRepository interface. Với khai báo như trên, Spring Data JPA sẽ tự động lấy đối tượng implement cho interface HelloRepository là SimpleJpaRepository như các bạn thấy trong hình ảnh ở trên để khởi tạo trong Spring container.
Một điểm mà các bạn lưu ý là chúng ta cần khai báo tag <context:annotation-config/> như mình đã làm ở trên để Spring cấu hình đối tượng của class EntityPathResolver khi khởi tạo bean cho class JpaRepositoryFactoryBean nhé! Nếu không thì sẽ bị lỗi “EntityPathResolver must not be null”. Các bạn có thể xem phương thức setEntityPathResolver() với annotation @Autowired trong class JpaRepositoryFactoryBean để hiểu rõ thêm chỗ này.
Vì đối tượng implement SimpleJpaRepository sử dụng transaction nên các bạn cần phải khai báo thêm bean transactionManager vào Spring container các bạn nhé.
XHTML <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <jpa:repositories base-package="com.huongdanjava.springdatajpa"/> <context:annotation-config/> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="persistenceUnitName" value="springdataPU"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/jpa_example"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> </beans>| 1234567891011121314151617181920212223242526272829303132333435363738 | <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:jpa="http://www.springframework.org/schema/data/jpa"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <jpa:repositories base-package="com.huongdanjava.springdatajpa"/> <context:annotation-config/> <bean id="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="dataSource"ref="dataSource"/><property name="persistenceUnitName"value="springdataPU"/><property name="jpaVendorAdapter"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/></property></bean> <bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName"value="com.mysql.cj.jdbc.Driver"/><property name="url"value="jdbc:mysql://localhost:3306/jpa_example"/><property name="username"value="root"/><property name="password"value="123456"/></bean> <tx:annotation-driven proxy-target-class="true"transaction-manager="transactionManager"/> <bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource"ref="dataSource"/></bean> </beans> |
OK, đến đây là chúng ta đã hoàn thành những phần cấu hình cần thiết. Giờ chạy ví dụ thử nhé các bạn.
Giả sử trong database mình đang có những dữ liệu sau đây:

thì khi chạy ví dụ sau đây:
Java package com.huongdanjava.springdatajpa; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); HelloRepository helloRepository = (HelloRepository) ac.getBean("helloRepository"); Student student = helloRepository.findById(new Long(2)).get(); System.out.println(student.getName()); } }| 12345678910111213141516 | packagecom.huongdanjava.springdatajpa; importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext; publicclassApplication{ publicstaticvoidmain(String[]args){ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml"); HelloRepository helloRepository=(HelloRepository)ac.getBean("helloRepository"); Student student=helloRepository.findById(newLong(2)).get();System.out.println(student.getName());}} |
Kết quả sẽ là:

Giả sử giờ chúng ta thêm một phương thức trong interface HelloRepository có nội dung như sau:
Java package com.huongdanjava.springdatajpa; import org.springframework.data.jpa.repository.JpaRepository; public interface HelloRepository extends JpaRepository<Student, Long> { public Student findByName(String name); }| 123456789 | packagecom.huongdanjava.springdatajpa; importorg.springframework.data.jpa.repository.JpaRepository; publicinterfaceHelloRepository extendsJpaRepository<Student,Long>{ publicStudent findByName(Stringname); } |
thì khi chạy ví dụ sau:
Java package com.huongdanjava.springdatajpa; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); HelloRepository helloRepository = (HelloRepository) ac.getBean("helloRepository"); Student student = helloRepository.findByName("Phong"); System.out.println(student.getId()); } }| 1234567891011121314151617 | packagecom.huongdanjava.springdatajpa; importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext; publicclassApplication{ publicstaticvoidmain(String[]args){ApplicationContext ac=newClassPathXmlApplicationContext("spring.xml"); HelloRepository helloRepository=(HelloRepository)ac.getBean("helloRepository"); Student student=helloRepository.findByName("Phong"); System.out.println(student.getId());}} |
kết quả sẽ là:

Như các bạn thấy, mặc dù không có bất kỳ class nào implement interface HelloRepository nhưng chúng ta vẫn truy vấn table student theo column name được. Giảm được rất nhiều code mà chúng ta cần phải làm phải không các bạn?
4/5 - (4 bình chọn)Từ khóa » Jpa Là Gì Spring Data Jpa Là Gì
-
Spring Data JPA Là Gì? Tại Sao Chúng Ta Cần Sử Dụng Nó? - Deft Blog
-
Giới Thiệu Về Spring JPA - Techmaster
-
JPA Là Gì? Sự Khác Nhau Giữa JPA Với Hibernate - STACKJAVA
-
Giới Thiệu Về Spring Data JPA - Tại Sao Cần Sử Dụng Nó?
-
Dùng Hibernate đã Lâu? Thế Bạn Có Biết JPA Là Gì? - Viblo
-
Tổng Quan Về JPA (Java Persistence API) | TopDev
-
Sự Khác Biệt Giữa Jpa Và Spring Data Jpa Là Gì?
-
Sử Dụng Spring Data JPA Trong SpringBoot - Le Vu Nguyen
-
Sự Khác Biệt Giữa Jpa Và Spring Data Jpa Là Gì? Thế Bạn Có Biết ...
-
Spring Data JPA – Giới Thiệu Các Tính Năng Và Cách Sử Dụng
-
Sử Dụng Spring Data Jpa Là Gì ? Giới Thiệu Về Spring Jpa
-
Spring Data Jpa Là Gì ? Tại Sao Chúng Ta Cần Sử Dụng Nó? Sử ...
-
Sự Khác Biệt Giữa JPA Và Hibernate (Công Nghệ) - Sawakinome
-
Hướng Dẫn Sử Dụng Spring Boot Và Spring Data JPA - Openplanning