[Workflow] Database Migrations For MySQL - sparc-software-hust/fmecg-web-server GitHub Wiki
Mỗi khi có trường mới update, việc thêm file migration sẽ không ảnh hưởng đến data và các trường hiện có. Các công cụ sử dụng:
- Library: Sequelize (yêu cầu có package
sequelize
vàsequelize-cli
- Version:
sequelize: ^6.37.1
vàsequelize-cli: ^6.22.1
- Reference: Sequelize Migrations
1. Giải thích flow
Flow migration chia làm 2 phần là schema migrations và data migrations (seed migrations). Sequelize có hỗ trợ chia làm 2 folder trong root directory:
- Folder
migrations
: chứa các file migrations được tạo từ command line (sẽ được trình bày ở dưới). - Folder
seeders
: chứa các file dummy data được tạo từ command line.
Khi chạy các câu lệnh liên quan đến migrations, Sequelize sẽ lấy data từ 2 folder và đọc config từ file.sequelizerc
. Các câu lệnh để chạy migration đã được config trongpackage.json
như dưới đây:
"migrate": "npx sequelize-cli db:migrate --name",
"migrate.all": "npx sequelize-cli db:migrate",
"migration.create": "npx sequelize-cli migration:generate --name",
"migration.rollback": "npx sequelize-cli db:migrate:undo",
"migration.rollback.name": "npx sequelize-cli db:migrate:undo --name",
"migration.rollback.all": "npx sequelize-cli db:migrate:undo:all",
"seed": "npx sequelize-cli db:seed --seed",
"seed.all": "npx sequelize-cli db:seed:all",
"seed.create": "npx sequelize-cli seed:generate --name",
"seed.rollback": "npx sequelize-cli db:seed:undo",
"seed.rollback.name": "npx sequelize-cli db:seed:undo --seed",
"seed.rollback.all": "npx sequelize-cli db:seed:undo:all"
Trong repo đã có các sẵn các file migrations. Nếu lần đầu chạy, chúng ta sẽ run 2 dòng sau:
npm run migrate.all
npm run seed.all
NOTE: Nếu run seed lỗi thì rollback và run lại:
npm run seed.rollback.all
npm run seed.all
Nếu thêm 1 trường mới vào bảng đã có sẵn, các bước sẽ được hướng dẫn trong 2.1
.
2. Các thao tác với migrations file
2.1. Schema migrations
- Tạo 1 file migration
npm run migrate.create name-of-file
Khi đó Sequelize sẽ tạo cho chúng ta 1 file với format timestamp-name-of-file.js
trong folder migrations
. Trong file sẽ có 2 hàm, up
và down
:
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up (queryInterface, Sequelize) {
/**
* Khi chạy migrate, Sequelize sẽ chạy hàm up
*
* Example:
* await queryInterface.createTable('users', { id: Sequelize.INTEGER });
*/
},
async down (queryInterface, Sequelize) {
/**
* Khi muốn huỷ migrate đã chạy trước đó, Sequelize sẽ chạy hàm down
*
* Example:
* await queryInterface.dropTable('users');
*/
}
};
Việc thêm data vào migration giống như cách làm với sequelize.define
trong các file models DTO.
Ví dụ khi thêm 1 trường hobby
vào bảng users
. Có 2 việc cần thực hiện:
- Tạo và chạy file migration
- Thêm trường
hobby
trongUserDTO.js
Hàm up
và down
được sửa như sau:
module.exports = {
async up(queryInterface, Sequelize) {
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.addColumn(
'users',
'hobby',
{
type: Sequelize.DataTypes.STRING,
},
{ transaction },
);
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
async down(queryInterface, Sequelize) {
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.removeColumn('users', 'hobby', { transaction });
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
};
- Chạy 1 file migration
npm run migrate name-of-file
hoặc (nếu đã chạy nhiều migration trước đó, Sequelize sẽ chỉ chạy những file migration mới được tạo), bạn chỉ cần:
npm run migrate
- Chạy tất cả migration (cho trường hợp chạy migrations lần đầu)
npm run migrate.all
- Undo lại 1 file migration bất kì
npm run migration.rollback.name name-of-file
- Undo lại migration gần nhất
npm run migration.rollback
- Undo tất cả các migrations
npm run migration.rollback.name
2.2. Seed migrations
- Tạo 1 seed
npm run seed.create name-of file
Sequelize sẽ tạo 1 file timestamp-name-of-file.js
trong folder seeders
. Cũng với 2 hàm up
và down
, flow giống như schema migrations
'use strict';
/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up (queryInterface, Sequelize) {
/**
* Add seed commands here.
*
* Example:
* await queryInterface.bulkInsert('People', [{
* name: 'John Doe',
* isBetaMember: false
* }], {});
*/
},
async down (queryInterface, Sequelize) {
/**
* Add commands to revert seed here.
*
* Example:
* await queryInterface.bulkDelete('People', null, {});
*/
}
};
NOTE: Đảm bảo phải await
mỗi command. Nếu không sẽ không báo lỗi nhưng không insert được.
- Chạy 1 file seed
npm run seed name-of-file
- Chạy tất cả seed files (cho trường hợp chạy dummy lần đầu)
npm run seed.all
- Undo lại 1 file seed bất kì
npm run seed.rollback.name name-of-file
- Undo lại seed gần nhất
npm run seed.rollback
- Undo tất cả các seeds
npm run seed.rollback.all