Bài trước: Web back-end (20) - Làm việc với Postgresql
-----
21 Lập trình với cơ sở dữ liệu
Như đã đề cập, để làm việc với hệ quản trị cơ sở dữ liệu (HQTCSDL), ngoài sử dụng công cụ dòng lệnh, công cụ đồ họa; chúng ta còn có thể sử dụng ngôn ngữ lập trình.
Chúng ta sẽ cùng tìm hiểu về cách sử dụng ngôn ngữ lập trình để làm việc với HQTCSDL (cũng được gọi là làm việc với cơ sở dữ liệu).
21.1 Code first và Database first
Trong phần này, chúng ta cùng tìm hiểu về hai cách tiếp cận phổ biến khi làm việc với cơ sở dữ liệu trong phát triển ứng dụng nói chung và trong phát triển ứng dụng web nói riêng. Đó là Code first và Database first.
Cả hai đều sử dụng công cụ ORM (Object-Relational Mapping) để ánh xạ giữa mã nguồn (thường là các đối tượng trong lập trình) và cơ sở dữ liệu quan hệ.
Code first
Code first là cách tiếp cận mà bạn định nghĩa mô hình dữ liệu trong mã nguồn trước (thường là các lớp hoặc đối tượng trong ngôn ngữ lập trình), sau đó sử dụng ORM để tự động tạo hoặc cập nhật schema cơ sở dữ liệu (bảng, cột, mối quan hệ) dựa trên mã nguồn.
Database first
Database first là cách tiếp cận mà bạn thiết kế cơ sở dữ liệu trước (tạo bảng, cột, mối quan hệ bằng SQL hoặc công cụ GUI), sau đó sử dụng ORM để sinh ra các mô hình (lớp hoặc đối tượng) trong mã nguồn dựa trên schema cơ sở dữ liệu.
Chọn cách tiếp cận nào?
Để biết chúng ta nên chọn cách tiếp cận nào. Chúng ta cùng xem xét ưu và nhược điểm của mỗi cách tiếp cận.
Ưu điểm
Nhược điểm
Khi nào nên sử dụng?
ORM (Object-Relational Mapping: Ánh xạ Quan hệ - Đối tượng) là một kỹ thuật (công cụ) lập trình cho phép ánh xạ giữa các đối tượng trong mã nguồn (thường là các lớp trong lập
trình hướng đối tượng) và các bảng trong cơ sở dữ liệu quan hệ.
ORM giúp lập trình viên thao tác với cơ sở dữ liệu bằng cú pháp của ngôn ngữ lập trình thay vì viết câu lệnh SQL trực tiếp, từ đó tăng hiệu suất phát triển, giảm độ phức tạp và cải thiện
tính bảo trì của mã nguồn.
Một số ORM phổ biến:
- Node.js: Sequelize, TypeORM, Prisma.
- Python: Django ORM, SQLAlchemy.
- Java: Hibernate, Spring Data JPA.
- Ruby: ActiveRecord (Ruby on Rails).
- PHP: Eloquent (Laravel).
21.3 Sequelize
Trước khi cài Sequelize, là công cụ để ánh xạ các đối tượng trong mã nguồn thành các bảng trong cơ sở dữ liệu, chúng ta sẽ cài đặt 2 gói có tên là pg và pg-hstore.
Gói pg
Pg là trình điều khiển (driver) PostgreSQL phổ biến và mạnh mẽ nhất cho Node.js. Nó cung cấp một bộ API để bạn có thể kết nối đến máy chủ PostgreSQL, thực hiện các truy vấn SQL, và xử lý kết quả trả về.
Gói pg-hstore
PostgreSQL cung cấp một kiểu dữ liệu đặc biệt gọi là hstore, cho phép bạn lưu trữ các cặp khóa-giá trị (key-value) trong một cột của bảng. Điều này rất hữu ích khi bạn có các thuộc tính động hoặc bán cấu trúc mà không muốn tạo ra các cột riêng biệt cho mỗi thuộc tính.
pg-hstore là một plugin hoặc tiện ích mở rộng cho thư viện pg. Nó cung cấp khả năng:
- Chuyển đổi giữa kiểu dữ liệu hstore của PostgreSQL và các đối tượng JavaScript. Khi bạn truy vấn dữ liệu có cột kiểu hstore, pg-hstore sẽ tự động chuyển đổi giá trị hstore từ cơ sở dữ liệu thành một đối tượng JavaScript (ví dụ: { key1: 'value1', key2: 'value2' }).
- Chuyển đổi các đối tượng JavaScript thành kiểu dữ liệu hstore khi bạn chèn hoặc cập nhật dữ liệu. Khi bạn muốn lưu trữ dữ liệu dưới dạng hstore từ ứng dụng Node.js, pg-hstore sẽ chuyển đổi đối tượng JavaScript của bạn thành định dạng hstore mà PostgreSQL có thể hiểu được.
Cài đặt: pg và pg-hstore:
- Mở cửa sổ dòng lệnh, di chuyển dấu nhắc chuột vào thư mục dự án (TeoShop)
- Nhập lệnh: E:\TeoShop>pnpm i -s pg pg-hstore
- Mở tập tin package.json để kiểm tra xem việc cài đặt pg và pg-hstore được chưa. Nếu có thông tin của 2 gói này trong mục dependencies là đã cài đặt thành công.
Cài đặt sequelize
- Mở cửa sổ dòng lệnh, di chuyển dấu nhắc chuột vào thư mục dự án (TeoShop)
- Nhập lệnh: E:\TeoShop>pnpm i -s sequelize
- Mở tập tin package.json để kiểm tra xem việc cài đặt sequelize được chưa. Nếu có thông tin của sequelize trong mục dependencies là đã cài đặt thành công.
Cài đặt sequelize-cli
- sequelize-cli là công cụ dòng lệnh (cli - command line interface) để ra lệnh cho sequelize
- Cài ở chế độ global
- Nhập lệnh: E:\TeoShop>npm i g sequelize-cli
E:\TeoShop>npm i -g sequelize-cli
run `npm fund` for details
npm notice
npm notice New major version of
npm available! 10.9.2 -> 11.3.0
npm notice Changelog:
https://github.com/npm/cli/releases/tag/v11.3.0
npm notice To update run: npm
install -g npm@11.3.0
npm notice
- Mở tập tin package.json sẽ không thấy thông tin gì về sequelize-cli. Vì cài đặt global nên bạn cần vào C:\Users\Teo\AppData\Roaming\npm\node_modules, bạn sẽ thấy được gói sequelize-cli.
21.4 Sử dụng sequelize
Lệnh sequelize init
Lệnh sequelize init được sử dụng để khởi tạo cấu trúc thư mục và các tập tin cấu hình
cần thiết cho một dự án có sử dụng sequelize.
Khi bạn chạy lệnh sequelize init trong thư mục gốc của dự án Node.js, Sequelize-CLI sẽ tạo ra các thư mục và tập tin sau:
- config/config.json (hoặc config/config.js tùy thuộc vào cấu hình): tập tin này chứa các cấu hình kết nối đến cơ sở dữ liệu cho các môi trường khác nhau (development, test, production). Bạn sẽ cần chỉnh sửa tập tin này để cung cấp thông tin đăng nhập và chi tiết kết nối đến cơ sở dữ liệu bạn muốn sử dụng (ví dụ: PostgreSQL, MySQL, SQLite, SQL Server).
- models/: thư mục này sẽ chứa các tập tin định nghĩa model của bạn. Mỗi tập tin model thường tương ứng với một bảng trong cơ sở dữ liệu. Bạn sẽ định nghĩa tên bảng, các cột, kiểu dữ liệu, và các ràng buộc trong các tập tin này.
- migrations/: thư mục này sẽ chứa các tập tin migration.
Migration là các tập tin JavaScript chứa mã nguồn để thực hiện các thay đổi lược đồ cơ sở dữ liệu theo thời gian (ví dụ: tạo bảng, thêm cột, sửa đổi cột). Sequelize-CLI cung cấp các lệnh để tạo, chạy và rollback các migration.
- seeders/: thư mục này sẽ chứa các tập tin seeder. Seeder là các tập tin JavaScript chứa mã nguồn để chèn dữ liệu mẫu ban đầu vào cơ sở dữ liệu (ví dụ: tạo các tài khoản người dùng quản trị ban đầu, thêm các danh mục sản phẩm mặc định). Sequelize-CLI cũng cung cấp các lệnh để chạy các seeder.
21.5 Bài tập
Câu hỏi 21.1 Phát biểu nào sau đây KHÔNG đúng về Code First và Database First trong lập trình với cơ sở dữ liệu?
A. Code First là phương pháp định nghĩa mô hình dữ liệu trong mã nguồn trước, sau đó ORM sẽ tạo hoặc cập nhật schema cơ sở dữ liệu.
B. Database First là phương pháp thiết kế cơ sở dữ liệu trước, sau đó ORM sẽ sinh ra các mô hình trong mã nguồn dựa trên schema đã có.
C. Cả Code First và Database First đều bỏ qua vai trò của ORM và cho phép lập trình viên tương tác trực tiếp với cơ sở dữ liệu bằng SQL.
D. Code First thường phù hợp với các dự án mới, trong khi Database First thích hợp với các dự án làm việc trên cơ sở dữ liệu đã tồn tại.
Câu hỏi 21.2 Phát biểu nào sau đây KHÔNG đúng về ORM (Object-Relational Mapping)?
A. ORM là một kỹ thuật lập trình giúp ánh xạ giữa các đối tượng trong mã nguồn và các bảng trong cơ sở dữ liệu quan hệ.
B. ORM làm tăng độ phức tạp của mã nguồn và giảm hiệu suất phát triển ứng dụng.
C. ORM cho phép lập trình viên thao tác với cơ sở dữ liệu bằng cú pháp của ngôn ngữ lập trình thay vì viết câu lệnh SQL trực tiếp.
D. Sequelize (Node.js) và Django ORM (Python) là những ví dụ về các ORM phổ biến
Câu hỏi 21.3 Bốn thư mục chính được tạo ra bởi lệnh sequelize init là config, models, migrations, và seeders. Phát biểu nào sau đây về mục đích của các thư mục này là KHÔNG đúng?
A. Thư mục migrations chứa các tập tin SQL script để thực hiện các thay đổi lược đồ cơ sở dữ liệu theo thời gian.
B. Thư mục config chứa các tập tin cấu hình kết nối đến cơ sở dữ liệu cho các môi trường phát triển, kiểm thử và sản xuất.
C. Thư mục models chứa các tập tin định nghĩa cấu trúc các bảng trong cơ sở dữ liệu dưới dạng các model (lớp) JavaScript.
D. Thư mục seeders chứa các tập tin JavaScript để chèn dữ liệu mẫu ban đầu vào cơ sở dữ liệu.
Bài tập 21.4 Cài đặt các gói trong bài học.
-----
Cập nhật: 5/5/2025
Bài sau: Web back-end (22) - Tạo cơ sở dữ liệu bằng Sequelize