"ORM" LÀ GÌ MÀ NHÀ NHÀ SỬ DỤNG?

Nếu bạn có kiến thức về ORM thì dễ dàng nhận thấy rằng hầu như các dự án ngày nay đều áp dụng các ORM framework vào sử dụng để khiến cho việc quản lý cơ sở dữ liệu và truy vấn trở nên dễ dàng hơn. Và cũng như bao công nghệ khác, ORM cũng sẽ có điểm mạnh và điểm trừ riêng ảnh hưởng đến dự án của bạn. Trong bài viết này, mình sẽ cùng các bạn tìm hiểu xem ORM là gì nhé!

Để khiến bài viết dễ dàng truyền đạt những kiến thức về ORM hơn thì mình sẽ sử dụng TypeORM - Một ORM phổ biến trong hệ sinh thái của Javascript làm mẫu nhé.


ĐỊNH NGHĨA ORM

ORM hay O/R mapping là tên viết tắt của Object Relational Mapping (Ánh xạ quan hệ đối tượng). Khi nghe tên tiếng Việt của kỹ thuật này các bạn đừng vội hốt hoảng 😀.

ORM là một kỹ thuật trong khoa học máy tính để chuyển đổi các dữ liệu trong hệ quản trị cơ sở dữ liệu sang các đối tượng tương thích bằng lập trình hướng đối tượng (OOP). Cụ thể hơn, ORM sẽ ánh xạ các dữ liệu trong database sang một lớp (class) nhất định trong mã nguồn. Bằng cách đó sẽ khiến cho việc kiến trúc, quản lí và duy trì những vấn đề liên quan đến cơ sở dữ liệu trở nên đơn giản hơn.

Cách ORM ánh xạ một trường dữ liệu sang các lớp trong mã nguồn

Lấy một ví dụ thức tế hơn để các bạn có thể hình dung về ORM, giả sử mình có hai bảng Customer BankAccount. Một Customer có thể có nhiều BankAccount nhưng một BankAccount chỉ có thể có một Customer duy nhất (quan hệ ManyToOne). Nếu sử dụng các cơ sở dữ liệu SQL, chúng ta sẻ phải viết các query để tạo bảng Customer BankAccount kèm theo đó là các trường của chúng. Và cứ mỗi lần cần lấy ra, truy vấn hay tìm kiếm các giá trị của bảng đó, chúng ta sẽ lại cần viết query để các làm việc đó. Ví dụ như "SELECT ___ FROM ___" (SQL).

Vậy nên ORM sẽ giải quyết các vấn đề này bằng việc thay thế việc viết query thông thường thành các schema dưới dạng class. Ở đây mình có Customer với các trường như name, age, address và bankAccounts thì tương ứng mình sẽ có lớp như sau:

Đối tượng Customer Entity với TypeORM

Và trong các lớp này cũng sẽ có một số method khác để trả về dữ liệu hay tìm kiếm dữ liệu. Trong MySQL để lấy một số trường của Customer theo id thì ta có

let customer = "SELECT name, address WHERE id = 10";
Truy vấn dữ liệu của table Customer trong MySQL

Nhưng với TypeORM thì mọi việc sẽ trở nên dễ dàng hơn

let customer = await Customer.findById([10]);
Một ví dụ cho truy vấn customer theo Id

ORM ARCHITECTURAL PATTERN (ORM MẪU KIẾN TRÚC)

ORM có một số mẫu kiến trúc (architectural pattern) chủ đạo  được áp dụng để triển khai vào quá trình phát triển ORM. Theo Martin Fowler trong quyển sách Patterns of Enterprise Application Architecture (2003) (Tạm dịch: Mô hình kiến trúc ứng dụng doanh nghiệp), tác giả đã đề cập đến hai pattern chủ đạo và cốt yếu để tạo thành ORM là Active Record (Ghi Hoạt Động)Data Mapper (Ánh Xạ Dữ Liệu).

Patterns of Enterprise Application Architecture (2003),

Active Record Pattern (Mẫu bản ghi hoạt động)

Vậy Active Record là gì? Theo như Wikipedia thì

Trong kỹ thuật phần mềm, mẫu bản ghi hoạt động được một số người  coi là một mẫu kiến ​​trúc và một số người khác gần đây là một mẫu chống  đối. Nó được tìm thấy trong phần mềm lưu trữ dữ liệu đối tượng trong bộ  nhớ trong cơ sở dữ liệu quan hệ.

Các ORM kiểu bản ghi hoạt động ánh xạ một đối tượng vào một hàng cơ sở dữ liệu. Trong ví dụ trên, chúng ta sẽ ánh xạ đối tượng Customer thành một hàng trong bảng Customer.

Tiếp cận với các ORM Active Record dễ thở hơn nhiều so với Data Mapper bởi để cập nhật một trường dữ liệu của đối tượng, bạn chỉ cần gọi phương thức save(). Điều này làm cho cách thức và ứng dụng của Active Record vào quá trình phát triển trở nên trực quan hơn.

Lấy ví dụ một cách ứng dụng theo hướng Active Record cùng với TypeORM, ta có:

Việc thao tác với Customer theo AR sẽ trông như trên

Các phương thức được mở rộng thêm cho đối tượng Customer sẽ được triển khai ngay bên trong lớp đối tượng Customer. Ví dụ ở đây mình thêm một phương thức để truy xuất dữ liệu Customer theo tên, mình sẽ thêm vào class Customer là

Lớp đối tượng Customer sau khi thêm phương thức findByName

Và để sử dụng phương thức được khai báo thì chúng ta chỉ cần gọi trực tiếp từ lớp đối tượng Customer

Một số ORM theo Active Record pattern phổ biến như

  • ActiveRecord
  • TypeORM
  • Sequelize
  • Eloquent
  • Prisma

Data Mapper Pattern (Mẫu ánh xạ dữ liệu)

Data Mapper là một mô hình ánh xạ hướng đối tượng (ORM). Khác với mô hình Active Record, Data Mapper giữ cho dữ liệu được lưu trong bộ nhớ máy và trong cơ sở dữ liệu độc lập với nhau. Mô hình Data Mapper phát  huy hiệu quả trong các ứng dụng có số luật lệ và quy trình nghiệp vụ phức tạp, hoặc khi phát triển một ứng dụng mới từ cơ sở dữ liệu có sẵn.

Đối với Active Record thì để thao tác với đối tượng được khai báo thì chúng ta có thể thao tác trực tiếp thông qua lớp đối tượng và lưu lại những gì được thay đổi qua phương thức save(). Tuy nhiên, đối với Data Mapper, các bạn không thể thao tác trực tiếp qua lớp đối tượng mà phải thông qua một service trung gian là Entity Manager. Nói thì nghe có vẻ khó hiểu nên mình sẽ dùng ví dụ dưới đây để minh họa nhé.

Với Active Record thì các bạn có thể thao tác qua lớp đối tượng Customer như ví dụ trên, nhưng với Data Mapper thì chúng ta cần làm như sau

Mọi logic đều được thao tác thông qua một Entity Manager

Và trong trường hợp này, nếu nhà phát triển muốn mở rộng thêm các phương thức cho để thuận lợi cho việc truy vấn thì cần phải khởi tạo thêm một lớp Repository khác để chứa các phương thức và hàm

Lớp CustomerRepository được khởi tạo chứa các phương thức được mở rộng

Một số ORM theo Data Mapper Pattern là

  • Hibernate
  • TypeORM
  • SQLALchemy
  • MikroORM
  • Doctrine 2

NÊN SỬ DỤNG ACTIVE RECORD VÀ DATA MAPPER KHI NÀO?

Mối mẫu kiến trúc sẽ có những điểm mạnh và điểm yếu riêng. Có thể dễ dàng thấy được rằng các Data Mapper Entity có khả năng để mở rộng và bảo trì hơn các Active Record Entity. Ngược lại các Active Record Entity sẽ thuận tợi hơn cho việc phát triển các ứng dụng nhỏ.


NÊN SỬ DỤNG ORM KHI NÀO

Như bao khía cạnh trong cuộc sống, ORM cũng có điểm mạnh và điểm yếu của chính nó.

Một điểm mạnh nổi bật của ORM là sự độc lập trong cú pháp khai báo và ứng dụng. Không cần biết đó là cơ sở dữ liệu NoSQL hay SQL, một số ORM như TypeORM đều cho ra các cú pháp như nhau nhưng chắc chắn sẽ có một số câu lệnh khác biệt bởi sự khác nhau về cấu trúc cơ sở dữ liệu. Tuy nhiên, điều đó là không đáng kể. Chỉ có sự khác nhau về ngôn ngữ lập trình bạn lựa chọn sử dụng để áp dụng ORM.

ORM cũng khá là dễ tiếp cận, điều này sẽ giảm thời gian dành cho những lập trình viên chưa học SQL bao giờ nhưng không có nhu cầu đào sâu.

Bên cạnh những điểm mạnh, hiệu năng của ORM sẽ khó mà có thể so sánh được với cách truy vấn thông thường. Vì trước khi biên dịch ra các câu truy vấn SQL thì cần có quá trình map data giữ các lớp đối tượng. Có một bài viết trên Viblo giải thích khá rõ về vấn đề này

Raw SQL vs Query Builder vs ORM
Giới thiệu Cơ sở dữ liệu là thành phần cốt lõi của việc lưu trữ trạng thái cho tất cả các trang web. Vì lí do đó, việc quan tâm đến sự tương tác dến cơ sở dữ liệu là vô cùng quan trọng để đảm bảo hệ...
SQL thuần vs Query Builder vs ORM

Và đó là tổng quát về ORM. Mình nghĩ đây là một kỹ thuật mà hầu hết lập trình viên nên biết để tối ưu hóa dự án cũng như nâng cao kiến thức khi thao tác với cơ sở dữ liệu.

Góc Của Chung

Góc Của Chung