- vừa được xem lúc

Lý thuyết Sequelize (Phần 1)

0 0 11

Người đăng: Tn Nguyen

Theo Viblo Asia

Trước khi đọc bài viết thì mình muốn mọi người biết rằng đây chỉ là bài dịch ngẫu hứng trong thời gian rảnh. Nếu các bạn thấy đọc khó hiểu thì hãy vào bài viết gốc của docs trên trang sequelize ở đường link này. Phiên bản mình dịch là Sequelize V6 ]

Lý thuyết Sequelize (phần I)

Lý thuyết cơ bản về model

I/ Khái niệm

Model chính là class đại diện cho bảng trong database. Để khai báo được bảng thì cần có những KIỂU DỮ LIỆU. Trong javascript thì không có những thứ đó nên Sequelize có hỗ trợ cho nhiều loại kiểu dữ liệu.

Sequelize hỗ trợ tạo sẵn bảng với dạng số nhiều của tên model. Ví dụ Model tên là User thì bảng trong database sẽ tên là Users. Và nếu bảng là Person thì Sequelize cũng sẽ tự hiểu dạng số nhiều là People nhờ vào thư viện inflection

Tên Model và tên bảng đều có thể thay đổi được.

II/ Cách khai báo Model

Sau đây là code mẫu sử dụng cả 2 cách sequelize và thừa hưởng class

  1. Sử dụng sequelize.define:
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:'); const User = sequelize.define('User', { // Model attributes are defined here firstName: { type: DataTypes.STRING, allowNull: false }, lastName: { type: DataTypes.STRING // allowNull defaults to true }
}, { // Other model options go here
}); // `sequelize.define` also returns the model
console.log(User === sequelize.models.User); // true
  1. Sử dụng thừa hưởng class
const { Sequelize, DataTypes, Model } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:'); class User extends Model {} User.init({ // Model attributes are defined here firstName: { type: DataTypes.STRING, allowNull: false }, lastName: { type: DataTypes.STRING // allowNull defaults to true }
}, { // Other model options go here sequelize, // We need to pass the connection instance modelName: 'User' // We need to choose the model name
}); // the defined model is the class itself
console.log(User === sequelize.models.User); // true

III/ Cẩn thận code shadowing

Nếu như sử dụng phương pháp thứ 2 là thừa hưởng class thì không nên khai báo trùng thuộc tính trong class mà model thừa hưởng.

Ví dụ không nên: (class Model đã có thuộc tính id, class User khai báo thêm thuộc tính id sẽ bị viết đè lên và mất setter getter)

// Invalid
class User extends Model { id; // this field will shadow sequelize's getter & setter. It should be removed. otherPublicField; // this field does not shadow anything. It is fine.
} User.init({ id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }
}, { sequelize }); const user = new User({ id: 1 });
user.id; // undefined

Ví dụ nên:

// Valid
class User extends Model { otherPublicField;
} User.init({ id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true }
}, { sequelize }); const user = new User({ id: 1 });
user.id; // 1

IV/ Thay đổi tên bảng

  1. Bắt buộc tên bảng y chang tên model:

Bằng cách sử dụng option freezeTableName: true

Ví dụ:

sequelize.define('User', { // ... (attributes)
}, { freezeTableName: true
});

Hoặc khai báo lựa chọn này khi khai báo sequelize ở đầu file

const sequelize = new Sequelize('sqlite::memory:', { define: { freezeTableName: true }
});
  1. Cung cấp tên bảng trực tiếp

Cung cấp tên bảng khi khai báo model:

sequelize.define('User', { // ... (attributes)
}, { tableName: 'Employees'
});

V/ Đồng bộ model

  1. Đồng bộ từng cái

Khi định nghĩa một model, tức là bạn đang nói cho Sequelize một vài điều về bảng của nó trong cơ sở dữ liệu. Tuy nhiên, nếu bảng thực sự không tồn tại ? Nếu nó tồn tại, nhưng nó có các cột khác nhau, ít cột hơn hoặc bất kỳ sự khác biệt nào?

Đây là lúc đồng bộ hóa model bước vào. Một model có thể được đồng bộ hóa với cơ sở dữ liệu bằng cách gọi model.sync(options), một hàm không đồng bộ (trả về một Promise ). Với lệnh gọi này, Sequelize sẽ tự động thực hiện truy vấn SQL tới cơ sở dữ liệu. Lưu ý rằng điều này chỉ thay đổi bảng trong cơ sở dữ liệu, không thay đổi model ở phía JavaScript.

  • User.sync() - Tạo bảng nếu nó không tồn tại (và không làm gì nếu nó đã tồn tại)
  • User.sync({ force: true }) - Tạo bảng, xóa bảng nếu bảng đã tồn tại rồi tạo bảng
  • User.sync({ alter: true }) - Kiểm tra trạng thái hiện tại của bảng trong cơ sở dữ liệu (cột nào tồn tại, kiểu dữ liệu của chúng, v.v.), sau đó thực hiện các thay đổi cần thiết trong bảng để khiến bảng phù hợp với model.

Ví dụ:

await User.sync({ force: true });
console.log("The table for the User model was just (re)created!");
  1. Đồng bộ tất cả

Bằng cách sử dụng lệnh sequelize.sync() để tự động đồng bộ tất cả model. Ví dụ:

await sequelize.sync({ force: true });
console.log("All models were synchronized successfully.");

VI/ Drop bảng

Để có thể drop bảng có liên hệ với lại một model ta chạy lệnh .drop():

await User.drop();
console.log("User table dropped!");

hoặc drop toàn bộ bảng ta chạy:

await sequelize.drop();
console.log("All tables dropped!");

Tuy nhiên drop bảng hoặc đồng bộ bằng phương pháp force, alter là KHÔNG KHUYẾN CÁO trong PRODUCTION.

VII/ Timestamps

Mặc định, sequelize sẽ thêm vào hai cột createAtupdateAt cho từng model với loại dữ liệu là DataTypes.DATE.

Chú ý: Những field này được cập nhật tự động bởi Sequelize. Do đó tất cả những cập nhật sử dụng Queries thường sẽ không kích hoạt tác dụng này. Mà phải cập nhật sử dụng hàm có sẵn của Sequelize.

Hành vi này có thể được tắt đi bởi lệnh:

sequelize.define('User', { // ... (attributes)
}, { timestamps: false
});

Hoặc là ta cũng có thể enable thằng nào mà mình thích bằng lệnh:

class Foo extends Model {}
Foo.init({ /* attributes */ }, { sequelize, // don't forget to enable timestamps! timestamps: true, // I don't want createdAt createdAt: false, // I want updatedAt to actually be called updateTimestamp updatedAt: 'updateTimestamp'
});

VIII/ Cú pháp ngắn để định nghĩa cột

Nếu như chỉ muốn định nghĩa type của một cột thì ta có thể viết:

// This:
sequelize.define('User', { name: { type: DataTypes.STRING }
}); // Can be simplified to:
sequelize.define('User', { name: DataTypes.STRING });

IX/ Giá trị mặc định của một cột

Mặc định sequelize sẽ coi giá trị mặc định là NULL nhưng ta có thể cấu hình giá trị mặc định:

sequelize.define('User', { name: { type: DataTypes.STRING, defaultValue: "John Doe" }
});

X/ Các kiểu dữ liệu

Sequelize hỗ trợ nhiều kiểu dữ liệu xài chung lẫn độc quyền cho từng database. Các kiểu dữ liệu độc quyền xem tại đây.

Ngoài ra các kiểu dữ liệu xài chung:

String

DataTypes.STRING // VARCHAR(255)
DataTypes.STRING(1234) // VARCHAR(1234)
DataTypes.STRING.BINARY // VARCHAR BINARY
DataTypes.TEXT // TEXT
DataTypes.TEXT('tiny') // TINYTEXT
DataTypes.CITEXT // CITEXT PostgreSQL and SQLite only.
DataTypes.TSVECTOR // TSVECTOR PostgreSQL only.

Boolean

DataTypes.BOOLEAN // TINYINT(1)

Numbers

DataTypes.INTEGER // INTEGER
DataTypes.BIGINT // BIGINT
DataTypes.BIGINT(11) // BIGINT(11) DataTypes.FLOAT // FLOAT
DataTypes.FLOAT(11) // FLOAT(11)
DataTypes.FLOAT(11, 10) // FLOAT(11,10) DataTypes.REAL // REAL PostgreSQL only.
DataTypes.REAL(11) // REAL(11) PostgreSQL only.
DataTypes.REAL(11, 12) // REAL(11,12) PostgreSQL only. DataTypes.DOUBLE // DOUBLE
DataTypes.DOUBLE(11) // DOUBLE(11)
DataTypes.DOUBLE(11, 10) // DOUBLE(11,10) DataTypes.DECIMAL // DECIMAL
DataTypes.DECIMAL(10, 2) // DECIMAL(10,2) DataTypes.INTEGER.UNSIGNED
DataTypes.INTEGER.ZEROFILL
DataTypes.INTEGER.UNSIGNED.ZEROFILL
// You can also specify the size i.e. INTEGER(10) instead of simply INTEGER
// Same for BIGINT, FLOAT and DOUBLE

Dates

DataTypes.DATE // DATETIME for mysql / sqlite, TIMESTAMP WITH TIME ZONE for postgres
DataTypes.DATE(6) // DATETIME(6) for mysql 5.6.4+. Fractional seconds support with up to 6 digits of precision
DataTypes.DATEONLY // DATE without time

UUIDs

{ type: DataTypes.UUID, defaultValue: DataTypes.UUIDV4 // Or DataTypes.UUIDV1
}

XI/ Các options khác của cột

const { Model, DataTypes, Deferrable } = require("sequelize"); class Foo extends Model {}
Foo.init({ // instantiating will automatically set the flag to true if not set flag: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true }, // default values for dates => current time myDate: { type: DataTypes.DATE, defaultValue: DataTypes.NOW }, // setting allowNull to false will add NOT NULL to the column, which means an error will be // thrown from the DB when the query is executed if the column is null. If you want to check that a value // is not null before querying the DB, look at the validations section below. title: { type: DataTypes.STRING, allowNull: false }, // Creating two objects with the same value will throw an error. The unique property can be either a // boolean, or a string. If you provide the same string for multiple columns, they will form a // composite unique key. uniqueOne: { type: DataTypes.STRING, unique: 'compositeIndex' }, uniqueTwo: { type: DataTypes.INTEGER, unique: 'compositeIndex' }, // The unique property is simply a shorthand to create a unique constraint. someUnique: { type: DataTypes.STRING, unique: true }, // Go on reading for further information about primary keys identifier: { type: DataTypes.STRING, primaryKey: true }, // autoIncrement can be used to create auto_incrementing integer columns incrementMe: { type: DataTypes.INTEGER, autoIncrement: true }, // You can specify a custom column name via the 'field' attribute: fieldWithUnderscores: { type: DataTypes.STRING, field: 'field_with_underscores' }, // It is possible to create foreign keys: bar_id: { type: DataTypes.INTEGER, references: { // This is a reference to another model model: Bar, // This is the column name of the referenced model key: 'id', // With PostgreSQL, it is optionally possible to declare when to check the foreign key constraint, passing the Deferrable type. deferrable: Deferrable.INITIALLY_IMMEDIATE // Options: // - `Deferrable.INITIALLY_IMMEDIATE` - Immediately check the foreign key constraints // - `Deferrable.INITIALLY_DEFERRED` - Defer all foreign key constraint check to the end of a transaction // - `Deferrable.NOT` - Don't defer the checks at all (default) - This won't allow you to dynamically change the rule in a transaction } }, // Comments can only be added to columns in MySQL, MariaDB, PostgreSQL and MSSQL commentMe: { type: DataTypes.INTEGER, comment: 'This is a column name that has a comment' }
}, { sequelize, modelName: 'foo', // Using `unique: true` in an attribute above is exactly the same as creating the index in the model's options: indexes: [{ unique: true, fields: ['someUnique'] }]
});

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 496

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 413

- vừa được xem lúc

Một số phương thức với object trong Javascript

Trong Javascript có hỗ trợ các loại dữ liệu cơ bản là giống với hầu hết những ngôn ngữ lập trình khác. Bài viết này mình sẽ giới thiệu về Object và một số phương thức thường dùng với nó.

0 0 134

- vừa được xem lúc

Tìm hiểu về thư viện axios

Giới thiệu. Axios là gì? Axios là một thư viện HTTP Client dựa trên Promise.

0 0 117

- vừa được xem lúc

Imports và Exports trong JavaScript ES6

. Giới thiệu. ES6 cung cấp cho chúng ta import (nhập), export (xuất) các functions, biến từ module này sang module khác và sử dụng nó trong các file khác.

0 0 93

- vừa được xem lúc

Bài toán đọc số thành chữ (phần 2) - Hoàn chỉnh chương trình dưới 100 dòng code

Tiếp tục bài viết còn dang dở ở phần trước Phân tích bài toán đọc số thành chữ (phần 1) - Phân tích đề và những mảnh ghép đầu tiên. Bạn nào chưa đọc thì có thể xem ở link trên trước nhé.

0 0 228