Bài viết được dịch và biên soạn bởi Nguyễn Hòa Khiêm(mobile: 0936439200-email: khiem31200@gmail.com) sinh viên đang học tại lớp Java Spring boot 07 từ bài viết Configuring a DataSource Programmatically in Spring Boot của tác giả Alejandro Ugarte .
Nguồn bài viết gốc : https://www.baeldung.com/spring-boot-configure-data-source-programmatic

1. Tổng quát

Spring boot sử dụng các thuật toán cố định để quét và cấu hình một nguồn dữ liệu. Nó cho phép chúng dễ dàng lấy một nguồn dữ liệu đã được cấu hình đầy đủ được triển khai theo mặc định.
Ngoài ra, Spring boot tự động cấu hình một nhóm kết nối(connection pool) nạp sẵn dữ liệu khi khởi động như là HikariCP, Apache Tomcat, hay Commons DBCP, theo thứ tự đó tùy thuộc vào từng classpath.
Spring boot tự động cấu hình nguồn dữ liệu rất tốt trong mọi trường hợp, tuy nhiên khi thoảng chúng ta cần một mức độ kiểm soát tốt hơn.Chúng ta sẽ phải thiết lập, triển khai nguồn dữ liệu và bỏ qua quá trình thiết lập tự động
Trong bài hướng dẫn dưới đây, chúng ta sẽ biết cách làm thế nào để cấu hình một nguồn dự liệu tự động trong Spring boot

2. Maven dependencies

Để tìm hiểu cách thực hiện điều này, chúng ta sẽ triển khai một lớp kho lưu trữ đơn giản, lớp này sẽ thực hiện các hoạt động CRUD trên một số thực thể JPA.
Chúng ta cần thêm những phụ thuộc sau (dependencies) vào file pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>2.4.1</version> 
    <scope>runtime</scope> 
</dependency>
Chúng ta sẽ sử dụng phiên bản phụ thuộc (dependency) spring-boot-starter-data-jpa mới nhất
Về cơ sở dữ liệu chúng ta sẽ sử dung H2 database để làm kho lưu trữ.

3. Cấu hình một nguồn dữ liệu có lập trình

Spring boot sẽ thực hiện tất cả hệ thống cơ sở hạ tầng nặng nề cho chúng ta.Bao gồm : Triển khai cơ sở dữ liệu H2, được HikariCP, Apache Tomcat hay Commons DBCP xử lý tự động và thiết lập cơ sở dữ liệu lưu trong bộ nhớ (In memory)
Ngoài ra, Chúng ta không cần phải tạo ra file application.properties, Spring boot sẽ cung cấp một vài cài đặt mặc định cơ sở dữ liệu
Đôi khi sẽ cần mức độ tùy chỉnh cao hơn, vì vậy chúng ta sẽ phải định cấu hình việc triển khai nguồn dữ liệu của riêng mình theo cách lập trình.
Cách dễ nhất để thực hiện điều này là xác định phương thức gốc của nguồn dữ liệu và đánh dấu nó với anotation @Configuration
@Configuration
public class DataSourceConfig {
    
    @Bean
    public DataSource getDataSource() {
        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.driverClassName("org.h2.Driver");
        dataSourceBuilder.url("jdbc:h2:mem:test");
        dataSourceBuilder.username("SA");
        dataSourceBuilder.password("");
        return dataSourceBuilder.build();
    }
}

Trong trường hợp này, để thuận tiện ta sẽ sử dụng DataSourceBuilder class để tạo tùy chỉnh đối tượng nguồn dự liệu

4. Cấu hình bên ngoài nguồn dữ liệu với file application.properties

Đầu tiên là chúng ta xác định một vài thuộc tính cơ bản của nguồn dữ liệu trong class Java
@Bean 
public DataSource getDataSource() { 
    DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); 
    dataSourceBuilder.username("SA"); 
    dataSourceBuilder.password(""); 
    return dataSourceBuilder.build(); 
}
Sau đó chúng ta cấu hình thêm một vài các thuộc tính khác trong application.properties
spring.datasource.url=jdbc:h2:mem:test
spring.datasource.driver-class-name=org.h2.Driver
Các thuộc tính được xác định trong nguồn bên ngoài, chẳng hạn như tệp application.properties hoặc một Java class được đánh dấu với Annotation @ConfigurationProperties sẽ ghi đè một cái khác tương tự được xác định trong Java API
Rõ ràng là với cách tiếp cận này, ta sẽ không còn lưu các cài đặt cấu hình nguồn dữ liệu của mình ở một nơi duy nhất.
Tuy nhiên, nó cho phép ta giữ các cài đặt cấu hình thời gian biên dịch và thời gian chạy được tách biệt độc đáo với nhau.
Điều này thực sự tốt, vì nó cho phép ta dễ dàng thiết lập điểm ràng buộc cấu hình. Bằng cách đó, chúng có thể bao gồm các cài đặt nguồn dữ liệu khác nhau từ các nguồn khác mà không cần phải cấu trúc lại các phương thức bean factory.

5. Kiểm tra thử cấu hình nguồn dữ liệu

5.1 Tạo ra một thực thể JPA(JPA Entity)

Tạo ra một class Java trong package Model (Nơi chứa các thông tin đối tượng)
@Entity
@Table(name = "users")
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String name;
    private String email;

    // standard constructors / setters / getters / toString
   // Chúng ta có thể sử dụng lombok ở đây để tạo constructors / setters / getters 
    
}

5.2 Tạo ra một lớp lưu trữ giữ liệu (Repository)

Ta cần triển khai một lớp kho lưu trữ cơ bản, cho phép chúng ta thực hiện các hoạt động CRUD(Thêm, sửa, xóa) trên các cá thể của lớp thực thể người dùng được định nghĩa ở trên.
Vì ta sử dụng Spring Data JPA, ta không cần tạo ra DAO . Ta chỉ đơn giản là mở rộng CrudRepository interface để triển khai kho lưu trữ làm việc.
@Repository
public interface UserRepository extends CrudRepository<User, Long> {}

5.3 Viết hàm kiểm thử lớp lưu trữ giữ liệu

Ta cần kiểm tra xem nguồn dữ liệu được cấu hình theo chương trình có thực sự hoạt động hay không. Ta có thể dễ dàng thực hiện điều này bằng một unit test
@RunWith(SpringRunner.class)
@DataJpaTest
public class UserRepositoryIntegrationTest {
    
    @Autowired
    private UserRepository userRepository;
   
    @Test
    public void whenCalledSave_thenCorrectNumberOfUsers() {
        userRepository.save(new User("Bob", "bob@domain.com"));
        List<User> users = (List<User>) userRepository.findAll();
        
        assertThat(users.size()).isEqualTo(1);
    }    
}
Lớp UserRepositoryIntegrationTest khá dễ hiểu. Nó chỉ đơn giản thực hiện hai trong số các phương thức CRUD của giao diện kho lưu trữ để duy trì và tìm các thực thể.

5.4 Chạy chương trình

Cuối cùng, chúng ta chạy chương trình sử dụng một phương thức main() mặc định
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner run(UserRepository userRepository) throws Exception {
        return (String[] args) -> {
            User user1 = new User("John", "john@domain.com");
            User user2 = new User("Julie", "julie@domain.com");
            userRepository.save(user1);
            userRepository.save(user2);
            userRepository.findAll().forEach(user -> System.out.println(user);
        };
    }
}
Ta đã kiểm tra lớp kho lưu trữ, vì vậy chắn rằng Nguồn dữ liệu đã được định cấu hình thành công. Do đó, nếu ta chạy ứng dụng mẫu,ta sẽ thấy trong bảng điều khiển xuất ra danh sách các thực thể Người dùng được lưu trữ trong cơ sở dữ liệu.

6. Kết luận

Trong bài viết trên ta đã biết được cách cấu hình nguồn dữ liệu trong lập trình Spring boot