Khởi tạo dữ liệu ban đầu trong Spring Boot
1. Tổng quan
Spring Boot giúp chúng ta có thể quản lý những thay đổi cơ sở dữ liệu của mình một cách rất dễ dàng. Nếu chúng ta để cấu hình như mặc định, nó sẽ tìm kiếm các thực thế (entity) trong các package để tự động tạo các bảng tương ứng
Tuy nhiên, đôi khi chúng ta lại cần một số kiểm soát chi tiết hơn đối với các thay đổi cơ sở dữ liệu. Và khi đó chúng ta có thể sử dụng các tệp như data.sql và schema.sql trong Spring
2. File data.sql
Ở đây chúng ta giả sử rằng đang ta đang sử dụng JPA và xác định một thực thể Country đơn giản trong dự án:
@Entity public class Country { @Id @GeneratedValue(strategy = IDENTITY) private Integer id; @Column(nullable = false) private String name; //... }
Nếu chúng ta chạy ứng dụng, Spring Boot sẽ tạo một bảng trống nhưng sẽ không có bất kì dữ liệu nào trong đó.
Và có một cách đơn giản để thực hiện việc này đó là chúng ta sẽ tạo ra một tệp có tên là data.sql:
INSERT INTO country (name) VALUES ('India'); INSERT INTO country (name) VALUES ('Brazil'); INSERT INTO country (name) VALUES ('USA'); INSERT INTO country (name) VALUES ('Italy');
Khi chúng ta chạy dự án và cấu hình file này với classpath, Spring sẽ chọn nó và sử dụng nó để thêm dữ liệu vào trong bảng cho chúng ta.
3. File schema.sql
Đôi khi chúng ta không muốn JPA tự tạo ra các bảng mặc định tự động. Khi đó chúng ta có thể sử dụng file schema.sql như sau:
CREATE TABLE country ( id INTEGER NOT NULL AUTO_INCREMENT, name VARCHAR(128) NOT NULL, PRIMARY KEY (id) );
Spring sẽ chọn file này và tạo cho chúng ta một bàng Country trong cơ sở dữ liệu của mình.
Nhưng các bạn cần phải nhớ tắt tính năng tự động tạo các bảng của JPA trong file application.properties để tránh bị xung đột khi tạo các bảng:
spring.jpa.hibernate.ddl-auto=none
4. Kiểm soát việc tạo cơ sở dữ liệu với Hibernate
Spring cung cấp một thuộc tính JPA cụ thể mà Hibernate có thể sử dụng nó để tạo ra DDL: spring.jpa.hibernate.ddl-auto.
Các thuộc tính của Hibernate gồm có: create, update, create-drop, validate và none.
- create: Trước tiên Hibernate sẽ drop các bảng đang có và sau đó tạo ra các bảng mới.
- update: Mô hình đối tượng được tạo dựa trên việc ánh xạ (thông qua các annotation hoặc XML) được so sánh với dữ liệu hiện có trong schema và sau đó Hibernate sẽ cập nhật lại schema với những thông tin mới. Nó sẽ không bao giờ xóa đi các bảng hay các cột đang có ngay cả khi chúng không còn được ứng dụng của ta yêu cầu nữa.
- create-drop: Tương tự như create nhưng sau khi tất cả các hoạt động đã được hoàn thành, Hibernate sẽ thực hiện việc drop database. Thường được sử dụng cho unit test.
- validate: Hibernate chỉ xác thực xem các bảng và các cột có tồn tại hay không, nếu không nó sẽ ném ra một ngoại lệ (exception).
- none: Giá trị này được dùng để tắt việc tạo DDL.
Với Spring Boot thuộc tính giá trị mặc định của DDL là create-drop nếu không có schema nào được khai bao, nếu đã được khai báo giá trị mặc định của nó sẽ là none.
5. @Sql
Spring còn cung cấp cho chúng ta annotation @Sql – một cách khai báo để khởi tạo và thêm giá trị vào schema được dùng để test.
Chúng ta hãy cùng tìm hiểu cách sử dụng annotation @Sql để tạo một bảng mới và đồng thời thêm dữ liệu mới vào trong bảng với integration test:
@Sql({"/employees_schema.sql", "/import_employees.sql"}) public class SpringBootInitialLoadIntegrationTest { @Autowired private EmployeeRepository employeeRepository; @Test public void testLoadDataForTestClass() { assertEquals(3, employeeRepository.findAll().size()); } }
Các thuộc tính của annotation @Sql là:
- config: cấu hình cục bộ cho các đoạn mã SQL.
- executionPhase: Chúng ta có thể chỉ định thời điểm sẽ thực thi các đoạn script.
- statements: Chúng ta có thể khai báo các câu lệnh SQL cùng dòng để thực thi.
- scripts: Chúng ta có thể khai báo các đường dẫn đến các file chứa đoạn script SQL để thực thi.
Annotation @Sql có thể được sử dụng ở mức class hoặc ở mức method:
@Test @Sql({"/import_senior_employees.sql"}) public void testLoadDataForTestCase() { assertEquals(5, employeeRepository.findAll().size()); }
6. @SqlConfig
Chúng ta có thể định cấu hình cách chạy các tập lệnh SQL bằng cách sử dụng annotation @SqlConfig.
@SqlConfig có thể được khai báo ở cấp độ class, nơi nó đóng vai trò là cấu hình toàn cục. Hoặc nó có thể được sử dụng để định cấu hình một annotation @Sql cụ thể.
Hãy cùng xem một ví dụ sau trong đó tôi chỉ định mã hóa các đoạn script SQL của mình:
@Test @Sql(scripts = {"/import_senior_employees.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = TransactionMode.ISOLATED)) public void testLoadDataForTestCase() { assertEquals(5, employeeRepository.findAll().size()); }
7. @SqlGroup
Java 8 trở lên cho phép sử dụng các annotation lặp lại. Tính năng này cũng có thể được sử dụng cho các annotation @Sql.
@SqlGroup({ @Sql(scripts = "/employees_schema.sql", config = @SqlConfig(transactionMode = TransactionMode.ISOLATED)), @Sql("/import_employees.sql")}) public class SpringBootSqlGroupAnnotationIntegrationTest { @Autowired private EmployeeRepository employeeRepository; @Test public void testLoadDataForTestCase() { assertEquals(3, employeeRepository.findAll().size()); } }
8. Kết luận
Trong bài viết này, chúng ta đã thấy cách tận dụng các file schema.sql và data.sql để thiết lập một schema ban đầu và thêm dữ liệu vào nó. Chúng ta cũng đã biết cách sử dụng annotation @Sql, @SqlConfig và @SqlGroup để tải dữ liệu test cho các đoạn test.
Nguồn: https://www.baeldung.com/spring-boot-data-sql-and-schema-sql
Leave a Reply