Với spring core chúng ta có jdbc thì với spring boot chúng ta có jpa (java persistence api), ở một mức độ trừu tượng cao hơn, đồng thời cũng tiện lợi hơn rất nhiều cho lập trình viên. Trong bài này Dũng sẽ cùng các bạn tìm hiểu về spring JPA nhé.

JPA

JPA là một tập hợp các interface tiêu chuẩn được định nghĩa trong bộ interface cho doanh nghiệp, cụ thể ở đây thì JPA bao gồm các interface, các anotation, các lớp dành cho phần kết nối cơ sở dữ liệu, ví dụ:

  1. Annotation Entity, Table: Để đánh dấu lớp ánh xạ với bảng trong cơ sở dữ liệu.
  2. Annotation Column: Để đánh dấu trường ánh xạ với trường trong cơ sở dữ liệu.
  3. Interface EntityManager: Chứa các hàm tương tác với một bảng trong cơ sở dữ liệu.
  4. Inteface EntityManagerFactory: chứa các hàm để tạo ra EntityManager.

Mô hình kết nối

Spring sử dụng JPA như một cầu nối (bridge design pattern) và gọi các interface hoặc các lớp giao tiếp với cơ sở dữ liệu là Repository (kho) theo mô hình như sau:

Các thành phần chúng ta nhìn thấy bao gồm:

  1. Service: Là các lớp xử lý nghiệp vụ của ứng dụng.
  2. Repository: Là các giao diện hoặc các lớp cầu nối đến cơ sở dữ liệu, thông thường thì chúng ta sẽ sử dụng interface.
  3. Database: Có thể là bất kỳ cơ sở dữ liệu nào, miễn là có cung cấp driver có kết nối qua JDBC.

Khởi tạo module

Chúng ta sẽ khởi tạo module có tên spring-boot-jpa.

Chuẩn bị

Chúng ta sẽ lưu dữ liệu từ hazelcast cache xuống cơ sở dữ liệu là mysql nên chúng ta sẽ cần tạo một cơ sở dữ liệu với một bảng như sau:

CREATE SCHEMA `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin ;

CREATE TABLE `persons` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8_bin;

Cấu hình dự án

Chúng ta sẽ cần thay đổi tập tin spring-boot-hazelcast/pom.xml với mã nguồn như sau:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>vn.techmaster</groupId>
        <artifactId>mastering-spring-boot</artifactId>
        <version>1.0.0</version>
    </parent>

    <artifactId>spring-boot-jpa</artifactId>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>${mysql.version}</version>
        </dependency>
    </dependencies>
</project>

Ở đây chúng bổ sung thư viện spring-boot-starter-jpa để có thể sử dụng các thành phần liên quan đến jpa. Ngoài ra chúng ta cũng cần bổ sung mysql-connector-j để kết nối đến cơ sở dữ liệu MySQL

Cấu hình

Chúng ta sẽ có tập tin cấu hình application.properties với nội dung như sau:

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=12345678
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect

Ở đây chúng ta có cấu hình cho jpa kết nối đến cơ sở dữ liệu mysql. Chúng ta cũng sẽ không cần bổ sung lớp cấu hình java nếu chỉ cần kết nối đến một cơ sở dữ liệu duy nhất và không có các yêu cầu quá đặc biệt.

Lớp dữ liệu

Chúng ta có thể khai báo một lớp dữ liệu Person thế này:

package vn.techmaster.jpa.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serializable;

@Getter
@Setter
@ToString
@Entity
@Table(name = "persons")
public class Person {

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

    private String name;
}

Lớp này chính là dạng Entity lưu vào cơ sở dữ liệu. Ở đây chúng ta sử dụng @Entity và @Table là các annotation của JPA để chỉ ra lớp Person này được ánh xạ đến bảng persons.
Ngoài ra chúng ta cũng sử dụng @Id annotation để nói rằng trường id ánh xạ đến khoá chính id của bảng, @GeneratedValue(strategy = GenerationType.IDENTITY) để nói rằng chúng ta sẽ sử dụng id do mysql sinh ra (tăng dần) mà không cần set khi khởi tạo entity.

Lớp Repository

Chúng ta sẽ khái báo một lớp PersonRepository để lưu dữ liệu vào mysql:

package vn.techmaster.jpa.repo;


import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import vn.techmaster.jpa.entity.Person;

import java.util.Collection;
import java.util.List;

@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {}

Ở đây chúng ta có:

  1. @Repository annotation để báo cho spring biết interface này là một lớp Repository, spring sẽ tự động cài đặt cho chúng ta thông qua java byte code, nghĩa là chúng ta sẽ không thấy lớp cài đặt đâu cả, đây là một trong những magic của java.
  2. Inteface JpaRepository sẽ cung cấp cho chúng ta các hàm cơ bản như save, saveAndFlush, findById, … Bạn có thể click vào interface này để xem các hàm có sẵn.

Khởi chạy chương trình

Để khởi chạy chương trình chúng ta sẽ cần tạo ra lớp SpringBootHazelcastStartUp với mã nguồn như sau:

package vn.techmaster.jpa;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationContext;
import vn.techmaster.jpa.entity.Person;
import vn.techmaster.jpa.repo.PersonRepository;

import java.util.Optional;

@EnableCaching
@SpringBootApplication
public class SpringBootJpaStartUp {

    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication
            .run(SpringBootJpaStartUp.class);
        PersonRepository personRepository = applicationContext
            .getBean(PersonRepository.class);
        Person person = new Person();
        person.setName("Techmaster");
        person = personRepository.save(person);
        System.out.println("save person: " + person);
        Optional<Person> fetchedPersonById = personRepository.findById(
            person.getId()
        );
        System.out.println("fetchedPersonById: " + fetchedPersonById);
    }
}

Chúng ta lưu một đối tượng Person vào cơ sử dữ liệu và rồi gọi để lấy ra, kết quả chúng ta nhận được là:

save person: Person(id=18, name=Techmaster)
fetchedPersonById: Optional[Person(id=18, name=Techmaster)]

Tổng kết

Như vậy chúng ta đã cùng nhau tìm hiểu spring jpa cơ bản để lưu và lấy dữ liệu ra từ cơ sở dữ liệu mysql.


Cám ơn bạn đã quan tâm đến bài viết|video này. Để nhận được thêm các kiến thức bổ ích bạn có thể:

  1. Đọc các bài viết của TechMaster trên facebook: https://www.facebook.com/techmastervn
  2. Xem các video của TechMaster qua Youtube: https://www.youtube.com/@TechMasterVietnam nếu bạn thấy video/bài viết hay bạn có thể theo dõi kênh của TechMaster để nhận được thông báo về các video mới nhất nhé.
  3. Chat với techmaster qua Discord: https://discord.gg/yQjRTFXb7a