Xem thêm

Simple demo về kiến trúc CQRS với Spring Boot

Huy Erick
CQRS là một mô hình kiến trúc cho việc xử lý CRUD dữ liệu, viết tắt của từ Command Query Responsibility Segregation. Mô hình này tách biệt hai thành phần chính là Command và Query....

Simple demo về kiến trúc CQRS với Spring Boot

CQRS là một mô hình kiến trúc cho việc xử lý CRUD dữ liệu, viết tắt của từ Command Query Responsibility Segregation. Mô hình này tách biệt hai thành phần chính là Command và Query.

  • Command: Các thao tác ghi dữ liệu - WRITE.
  • Query: Các thao tác đọc dữ liệu - READ.

Tư tưởng của CQRS là tách biệt thao tác Query và Command để tránh ảnh hưởng phụ đến quá trình kinh doanh và tạo ra những luồng xử lý rõ ràng, chặt chẽ.

Được gói gọn như sau:

  • Query: Là các thao tác select và trả về dữ liệu, nhưng không thay đổi trạng thái của hệ thống.
  • Command: Là các thao tác thay đổi dữ liệu/thay đổi trạng thái hệ thống, nhưng không trả về dữ liệu.

Mục đích của bài viết này là trình bày cách áp dụng CQRS vào coding, không nhằm giải thích các lập luận.

CQRS với Spring Boot demo

Trong bài viết này, chúng ta sẽ sử dụng Spring Boot để tạo một demo nhỏ về CQRS.

Để tạo dự án Spring Boot, bạn có thể sử dụng https://start.spring.io/ hoặc trên IDE như Intelij.

Cấu trúc dự án thông thường sẽ bao gồm các lớp như sau:

  • Service layer:

    • IBookQueryService
    • IBookCommandService
  • Controller layer:

    • BookQueryController
    • BookCommandController
  • Representations:

    • BookQueryDto
    • BookCreateCommandDto

Service

Thao tác giữa 2 vai trò READ và WRITE được tách biệt trong IBookQueryServiceIBookCommandService như sau:

public interface IBookQueryService {
    List getAllBooks();
    Book getBookInfo(String bookId);
}

public interface IBookCommandService {
    void create(String name, Date publishDate);
}

Controller

BookQueryController sẽ gồm các resource SELECT và sẽ Autowired IBookQueryService ở Query Controller tương ứng:

@Controller
public class BookQueryController {
    @Autowired
    private IBookQueryService bookQueryService;

    @GetMapping("/books")
    @ResponseBody
    public List allBooks() {
        return bookQueryService.getAllBooks();
    }

    @GetMapping("/books/{bookId}")
    @ResponseBody
    public ResponseEntity bookInfo(@PathVariable("bookId") String bookId) {
        Book bookInfo = bookQueryService.getBookInfo(bookId);
        if (bookInfo == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(bookInfo);
    }
}

@Controller
public class BookCommandController {
    @Autowired
    private IBookCommandService bookCommandService;

    @PostMapping("/book/create")
    @ResponseStatus(HttpStatus.OK)
    public void createBook(@RequestBody BookCreateCommandDto dto) {
        bookCommandService.create(dto.getName(), dto.getPublishDate());
    }
}

Representations

Tiếp theo là các data transfer object, các lớp này sẽ được convert từ Entity.

Trong ví dụ này, Book là một minh họa của class Entity mapping với table trong database.

@Data
public class BookCreateCommandDto {
    private String name;
    private Date publishDate;
}

Cơ bản, chúng ta đã trình bày xong tổng quát về CQRS.

Tư tưởng của CQRS rất rõ ràng và chặt chẽ. Một Query request cần được tách biệt với Command request.

  • Query: Chỉ select và trả về dữ liệu, nhưng không thay đổi dữ liệu.
  • Command: Thay đổi dữ liệu, nhưng không trả về dữ liệu.

Nếu bạn quan tâm, bạn có thể tải mã nguồn đầy đủ từ đường dẫn sau: Full source code demo

1