Sequelize是Nodejs生態中一個比較出名的ORM框架。經過ORM框架,可使用對象來操做數據庫表數據,提升了開發效率和代碼可讀性,也方便後期維護。node
今天主要介紹經過遷移[Migration]
來建立數據庫,表。mysql
遷移的好處,能夠類比git。經過每次建立遷移文件,來支持更新,回滾數據庫表結構,也方便協同開發,也避免人工手動去直接修改數據庫,用代碼自動管理。換個電腦,也不用去拷貝數據庫,直接運行遷移就能夠徹底恢復開發環境,極大減輕了心智負擔。git
mkdir node_work
cd node_work
mkdir app
npm init -y
npm i sequelize-cli sequelize mysql2 koa
複製代碼
npx sequelize init
複製代碼
運行以後,會產生四個目錄:sql
config, migrations, models, seeders數據庫
config:npm
{
"development": {
"username": "root",
"password": "root",
"database": "app_development",
"host": "127.0.0.1",
"port": 8889,
"dialect": "mysql",
"timezone": "+08:00"
},
"test": {
"username": "root",
"password": null,
"database": "app_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "app_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
複製代碼
環境env => {配置}json
不一樣環境,對應不一樣的配置,也能夠自定義環境,好比homepromise
env指的是process.env.NODE_ENV
,bash
能夠經過設置環境變量來改變,好比export NODE_ENV=production
;cookie
遷移時候,也能夠指定環境:npx sequelize db:migrate --env production
,來鏈接production對應配置的數據庫
建立數據庫:
npx sequelize db:create
複製代碼
說明
npx
是npm5.2以後,自帶的一個命令。能夠不用全局安裝sequelize,使用時候,若是本地沒有,就去npm倉庫下載;下載完後或者本地已經下載過,就運行腳本命令。這樣能夠避免本地全局包過時,環境問題,每次都使用最新版本
migrations: 遷移文件
npx sequelize model:generate --name User --attributes username:string
複製代碼
執行後,會生成20180918055558-create-user.js
遷移文件,和models/user.js
模型文件
其餘字段能夠在遷移文件中補全,最後再運行npx sequelize db:migrate
,就能夠在數據庫中看到生成了users表
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
username: {
type: Sequelize.STRING(20),
allowNull: false
},
password: {
type: Sequelize.CHAR(32),
allowNull: false
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
}, {
tableName: 'users',
charset: 'utf8mb4',
collate: 'utf8mb4_bin',
define: {
timestamps: true
}
}).then(() => {
// 添加索引
return queryInterface.addIndex('users', {
name: 'username',
unique: true,
fields: ['username']
});
});
},
// 回退時執行,刪除表
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
}
};
複製代碼
執行遷移:
npx sequelize db:migrate
npx sequelize db:migrate:all
複製代碼
撤銷遷移:
npx sequelize db:migrate:undo 最近一次的
npx sequelize db:migrate:undo:all
npx sequelize db:migrate:undo:all --to XXXXXXXXXXXXXX-create-posts.js
複製代碼
--from, --to
參數,能夠指定遷移文件
models: 模型文件
model:generate
生成的model都在這個目錄中
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
username: {
type: Sequelize.STRING(20),
allowNull: false
},
password: {
type: Sequelize.CHAR(32),
allowNull: false
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
},
{
tableName: 'users',
charset: 'utf8mb4',
collate: 'utf8mb4_bin',
}).then(() => {
return queryInterface.addIndex('users', {
name: 'username',
unique: true,
fields: ['username']
});
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Users');
}
};
複製代碼
模型對象建立,默認會自動賦值,更新createdAt, updatedAt兩個timestamps字段。下邊會給出完整示例。
seeders: 填充數據文件
建立seed文件:
npx sequelize seed:generate --name demo-user
複製代碼
執行以後,會獲得20180918090545-demo-user.js
'use strict';
const md5 = require('md5')
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.bulkInsert('Users', [
{
username: 'Kimoo',
password: md5('123456'),
createdAt: new Date(),
updatedAt: new Date(),
},
{
username: 'Reci',
password: md5('123321'),
createdAt: new Date(),
updatedAt: new Date(),
}
], {});
},
down: (queryInterface, Sequelize) => {
/*
Add reverting commands here.
Return a promise to correctly handle asynchronicity.
Example:
return queryInterface.bulkDelete('Person', null, {});
*/
return queryInterface.bulkDelete('Users', null, {});
}
};
複製代碼
填充數據:
npx sequelize db:seed:all
複製代碼
撤銷數據:
npx sequelize db:seed:undo 最近一次的
npx sequelize db:seed:undo --seed name-of-seed-as-in-data 具體某個
npx sequelize db:seed:undo:all
複製代碼
app.js
(async function() {
const Koa = require('koa');
const KoaStaticCache = require('koa-static-cache');
const KoaBodyParser = require('koa-bodyparser');
const router = require('./routers/main');
const Session = require('koa-session');
const app = new Koa();
// app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');
app.keys = ['app'];
app.use( Session({
key: 'koa:sess',
maxAge: 86400000,
autoCommit: true,
overwrite: true,
httpOnly: true,
signed: true,
rolling: false,
renew: false
}, app) );
// app.use( async (ctx, next) => {
// ctx.set('Access-Control-Allow-Origin','*');
// await next();
// } );
app.use( KoaStaticCache('./public', {
prefix: 'public',
gzip: true
}) );
app.use( KoaBodyParser() );
app.use( router.routes() );
app.listen(8088);
})();
複製代碼
models/index.js
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
// 自動導入 models 文件夾下的全部文件,好比user.js這個模型文件
// 自動加載模型並執行
// let users = require('./users');
// let UsersModel = users(sequelize, Sequelize);
// db[UsersModel.name] = UsersModel; // db['Users'] = UsersModel;
// 下面經過fs自動加載全部的文件,並執行,同時生成的模型對象掛載到db對象下面,最後返回出去
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
複製代碼
routers/main.js
const KoaRouter = require('koa-router');
const md5 = require('md5');
const Models = require('../models');
const Sequelize = require('sequelize');
const router = new KoaRouter();
router.post('/register', async ctx => {
// console.log(ctx.request.body);
let username = ctx.request.body.username.trim();
let password = ctx.request.body.password.trim();
let repassword = ctx.request.body.repassword.trim();
if (username=='' || password == '' || repassword == '') {
return ctx.body = {
code: 1,
data: '用戶名或密碼不能爲空'
}
}
if (password != repassword) {
return ctx.body = {
code: 2,
data: '兩次輸入的密碼不一致'
}
}
let user = await Models.Users.findOne({
where: {
username
}
});
if (user !== null) {
return ctx.body = {
code: 3,
data: '當前用戶已經被註冊了'
}
}
let newUser = await Models.Users.build({
username,
password: md5(password)
}).save();
ctx.body = {
code: 0,
data: {
id: newUser.get('id'),
username: newUser.get('username')
}
}
});
router.post('/login', async ctx => {
let username = ctx.request.body.username;
let password = ctx.request.body.password;
let user = await Models.Users.findOne({
where: {
username
}
});
if (user === null) {
return ctx.body = {
code: 1,
data: '不存在該用戶'
}
}
if (user.get('password') !== md5(password)) {
return ctx.body = {
code: 1,
data: '密碼錯誤'
}
}
// ctx.cookies.set('uid', user.get('id'), {
// httpOnly: false
// });
// 服務端發送一個約定好的cookie,來表示當前是登陸
// ctx.cookies.set('uid', user.get('id'), {
// // httpOnly,表示當前的cookie是否容許客戶端進行操做(js),若是爲true,那麼就表示這個cookie是能用戶http協議的數據傳輸
// httpOnly: true,
// signed: true
// });
ctx.cookies.set('username', user.get('username'), {
httpOnly: false
});
ctx.session.uid = 1;
ctx.body = {
code: 0,
data: {
id: user.get('id'),
username: user.get('username')
}
}
});
})
module.exports = router;
複製代碼
能夠在postman
中測試接口,地址http://localhost:8088/register
,註冊用戶
node app.js
複製代碼