Thiết kế kiến trúc và nguyên lý hoạt động của AutoTable

AutoTable là một framework tự động đồng bộ cấu trúc bảng cơ sở dữ liệu dựa trên các annotation trong entity Java. Dự án mã nguồn mở tại: https://gitcode.com/dromara/auto-table

Framework này tận dụng mô hình chiến lược (strategy pattern) và hệ thống annotation để tự động tạo hoặc cập nhật schema bảng khi ứng dụng khởi động. Kiến trúc được chia thành bốn thành phần chính: lõi, chiến lược, plugin tích hợp và kiểm thử — hỗ trợ đa nền tảng CSDL và dễ mở rộng.

Kiến trúc tổng thể

AutoTable được thiết kế theo hướng mô-đun hóa cao, tập trung vào khả năng tự động phát hiện thay đổi từ entity và áp dụng lên CSDL. Hệ thống gồm ba khía cạnh chính: phân tách mô-đun, các thành phần cốt lõi và luồng xử lý.

Phân chia mô-đun

  1. Mô-đun lõi (auto-table-core): Chịu trách nhiệm phân tích annotation, xây dựng metadata bảng và quản lý chiến lược thực thi. Điểm khởi chạy là AutoTableBootstrap.
  2. Mô-đun chiến lược (auto-table-strategy-*): Cung cấp triển khai riêng cho từng hệ quản trị CSDL (MySQL, PostgreSQL, Oracle...), tuân thủ giao diện IStrategy.
  3. Mô-đun plugin (auto-table-spring-boot-starter, auto-table-solon-plugin): Hỗ trợ tích hợp sẵn với Spring Boot và Solon mà không cần cấu hình phức tạp.
  4. Mô-đun kiểm thử (auto-table-test-*): Đảm bảo tính ổn định qua các bài test đơn vị và tích hợp.

Các thành phần cốt lõi

Thành phần Mô tả
AutoTableGlobalConfig Quản lý cấu hình toàn cục, cho phép đăng ký chiến lược hoặc builder tùy chỉnh.
AutoTableBootstrap Điểm khởi chạy chính, quét entity và kích hoạt quá trình đồng bộ bảng.
TableMetadata Đối tượng biểu diễn metadata của bảng: tên bảng, cột, khóa chính, chỉ mục...
IStrategy Giao diện định nghĩa logic thao tác CSDL đặc thù cho từng loại hệ quản trị.
DatabaseBuilder Sinh và thực thi câu lệnh SQL dựa trên metadata đã xây dựng.
DataSourceManager Quản lý kết nối CSDL, hỗ trợ đa nguồn dữ liệu và chuyển đổi động.

Luồng xử lý

  1. Phân tích annotation: Quét các lớp có đánh dấu @AutoTable, trích xuất thông tin để tạo TableMetadata.
  2. Chọn chiến lược: Dựa vào loại CSDL đang dùng, chọn triển khai phù hợp của IStrategy.
  3. So sánh cấu trúc: Chiến lược so sánh schema hiện tại với metadata mục tiêu, xác định khác biệt.
  4. Thực thi SQL: DatabaseBuilder sinh và chạy các lệnh ALTER/CREATE TABLE tương ứng.

Mẫu thiết kế được áp dụng

  • Strategy Pattern: Tách biệt logic CSDL cụ thể ra khỏi lõi framework.
  • Builder Pattern: Dùng để xây dựng TableMetadata và sinh SQL một cách linh hoạt.
  • Observer Pattern: Hỗ trợ callback như AutoTableFinishCallback để can thiệp vào các mốc quan trọng.

Chi tiết mô-đun lõi và tương tác

Mô-đun lõi đảm nhận vai trò trung tâm, kết nối tất cả các phần còn lại để hoàn thành quá trình ánh xạ từ entity sang bảng CSDL.

Các thành phần chính

  • AutoTableBootstrap: Khởi tạo toàn bộ quy trình.
  • AutoTableGlobalConfig: Lưu trữ và cấp phát cấu hình mở rộng.
  • DataSourceManager: Quản lý ngữ cảnh kết nối CSDL.
  • TableMetadataHandler: Phân tích entity và tạo metadata.
  • DatabaseBuilder: Thực thi thay đổi cấu trúc.
  • IStrategy: Triển khai logic CSDL cụ thể.

Ví dụ sử dụng

@Data
@AutoTable
public class User {
    @PrimaryKey
    private Long id;

    @ColumnName("user_name")
    private String name;

    @ColumnNotNull
    private Integer age;
}

Nguyên lý tự động tạo bảng

Quá trình tự động tạo bảng bắt đầu từ việc quét các lớp entity có annotation @AutoTable.

1. Xây dựng metadata

Lớp DefaultTableMetadataBuilder phân tích các trường và annotation để tạo đối tượng TableMetadata. Ví dụ:

public class DefaultTableMetadataBuilder {
    public TableMetadata build(Class<?> entityClass) {
        // Trích xuất thông tin bảng từ annotation
        return new TableMetadata(entityClass);
    }
}

2. Áp dụng chiến lược CSDL

Mỗi hệ quản trị CSDL có cú pháp riêng. Ví dụ triển khai cho MySQL:

public class MysqlStrategy implements IStrategy {
    @Override
    public List<String> generateCreateSql(TableMetadata meta) {
        StringBuilder sql = new StringBuilder("CREATE TABLE ");
        // ... xây dựng câu lệnh CREATE TABLE theo chuẩn MySQL
        return Collections.singletonList(sql.toString());
    }
}

3. Sinh và thực thi SQL

Sau khi có danh sách câu lệnh, hệ thống dùng DataSourceManager để lấy kết nối và thực thi:

try (Connection conn = DataSourceManager.getConnection()) {
    for (String stmt : sqlStatements) {
        try (Statement s = conn.createStatement()) {
            s.execute(stmt);
        }
    }
}

4. Cơ chế callback và interceptor

Người dùng có thể đăng ký interceptor để điều chỉnh metadata trước khi sinh SQL, hoặc callback để xử lý sau khi hoàn tất.

5. Hỗ trợ đa nguồn dữ liệu

Thông qua DataSourceManager.setDataSource(...), AutoTable có thể làm việc với nhiều CSDL cùng lúc. Mỗi entity có thể được ánh xạ tới một nguồn dữ liệu riêng.

Thiết kế hỗ trợ đa nguồn dữ liệu

AutoTable cung cấp giao diện IDataSourceHandler để tích hợp với các cơ chế quản lý nguồn dữ liệu hiện có.

Giao diện cốt lõi

public interface IDataSourceHandler {
    String resolveDataSource(Class<?> entityClass);
    void switchTo(String dsName);
    void cleanup();
}

Tích hợp với Spring Boot

Khi dùng cùng Dynamic Datasource, triển khai có thể như sau:

@Component
public class SpringDsHandler implements IDataSourceHandler {
    @Override
    public String resolveDataSource(Class<?> clazz) {
        Ds ds = clazz.getAnnotation(Ds.class);
        return ds != null ? ds.value() : "primary";
    }

    @Override
    public void switchTo(String name) {
        DynamicDataSourceContextHolder.setContextKey(name);
    }

    @Override
    public void cleanup() {
        DynamicDataSourceContextHolder.clear();
    }
}

Tích hợp với ứng dụng thuần Java

Trong môi trường không có Spring, người dùng tự quản lý map DataSource:

public class StandaloneDsHandler implements IDataSourceHandler {
    private final Map<String, DataSource> sources = new ConcurrentHashMap<>();

    @Override
    public void switchTo(String name) {
        DataSource ds = sources.computeIfAbsent(name, this::createDataSource);
        DataSourceManager.setDataSource(ds);
    }

    // ... các phương thức còn lại
}

Nhờ thiết kế mở và tách biệt rõ ràng, AutoTable dễ dàng thích nghi với nhiều kiến trúc ứng dụng khác nhau, từ monolith đến microservice.

Thẻ: Java orm database-migration annotation-processing strategy-pattern

Đăng vào ngày 17 tháng 05 lúc 13:47