package.json
{
"name": "model-sequelize",
"version": "1.0.0",
"description": "Sequelize best practice example with async",
"main": "app.js",
"scripts": {
"start": "node --use_strict app.js"
},
"keywords": [
"sequelize",
"async"
],
"author": "Michael Liao",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/michaelliao/learn-javascript.git"
},
"dependencies": {
"sequelize": "3.24.1",
"mysql": "2.11.1"
}
}
db.js
const Sequelize = require('sequelize');
const uuid = require('node-uuid');
const config = require('./config');
console.log('init sequelize...');
function generateId() {
return uuid.v4();
}
var sequelize = new Sequelize(config.database, config.username, config.password, {
host: config.host,
dialect: config.dialect,// 指定连接的数据库类型
pool: {
max: 5,// 连接池中最大连接数量
min: 0,// 连接池中最小连接数量
idle: 10000// 如果一个线程 10 秒钟内没有被使用过的话,那么就释放线程
}
});
const ID_TYPE = Sequelize.STRING(50);
function defineModel(name, attributes) {
var attrs = {};
for (let key in attributes) {
let value = attributes[key];
if (typeof value === 'object' && value['type']) {
value.allowNull = value.allowNull || false;
attrs[key] = value;
} else {
attrs[key] = {
type: value,
allowNull: false
};
}
}
attrs.id = {
type: ID_TYPE,
primaryKey: true
};
attrs.createdAt = {
type: Sequelize.BIGINT,
allowNull: false
};
attrs.updatedAt = {
type: Sequelize.BIGINT,
allowNull: false
};
attrs.version = {
type: Sequelize.BIGINT,
allowNull: false
};
console.log('model defined for table: ' + name + '\n' + JSON.stringify(attrs, function (k, v) {
if (k === 'type') {
for (let key in Sequelize) {
if (key === 'ABSTRACT' || key === 'NUMBER') {
continue;
}
let dbType = Sequelize[key];
if (typeof dbType === 'function') {
if (v instanceof dbType) {
if (v._length) {
return `${dbType.key}(${v._length})`;
}
return dbType.key;
}
if (v === dbType) {
return dbType.key;
}
}
}
}
return v;
}, ' '));
return sequelize.define(name, attrs, {
tableName: name,
timestamps: false,
hooks: {
beforeValidate: function (obj) {
let now = Date.now();
if (obj.isNewRecord) {
console.log('will create entity...' + obj);
if (!obj.id) {
obj.id = generateId();
}
obj.createdAt = now;
obj.updatedAt = now;
obj.version = 0;
} else {
console.log('will update entity...');
obj.updatedAt = now;
obj.version++;
}
}
}
});
}
const TYPES = ['STRING', 'INTEGER', 'BIGINT', 'TEXT', 'DOUBLE', 'DATEONLY', 'BOOLEAN'];
var exp = {
defineModel: defineModel,
sync: () => {
// only allow create ddl in non-production environment:
if (process.env.NODE_ENV !== 'production') {
console.log('db.js - sync() called');
return sequelize.sync({ force: true });
} else {
throw new Error('Cannot sync() when NODE_ENV is set to \'production\'.');
}
}
};
for (let type of TYPES) {
exp[type] = Sequelize[type];
}
exp.ID = ID_TYPE;
exp.generateId = generateId;
module.exports = exp;
models
Pet.js
const db = require('../db');
module.exports = db.defineModel('pets', {
ownerId: db.ID,
name: db.STRING(100),
gender: db.BOOLEAN,
birth: db.STRING(10),
});
User.js
const db = require('../db');
module.exports = db.defineModel('users', {
email: {
type: db.STRING(100),
unique: true
},
passwd: db.STRING(100),
name: db.STRING(100),
gender: db.BOOLEAN
});
config-default.js
var config = {
dialect: 'mysql',
database: 'nodejs',
username: 'www',
password: 'www',
host: 'localhost',
port: 3306
};
module.exports = config;
config-test.js
var config = {
dialect: 'mysql',
database: 'test',
username: 'www',
password: 'www',
host: 'localhost',
port: 3306
};
module.exports = config;
config.js
// config files:
const defaultConfig = './config-default.js';
const overrideConfig = './config-override.js';
const testConfig = './config-test.js';
const fs = require('fs');
var config = null;
if (process.env.NODE_ENV === 'test') {
console.log(`Load ${testConfig}...`);
config = require(testConfig);
} else {
console.log(`Load ${defaultConfig}...`);
config = require(defaultConfig);
try {
if (fs.statSync(overrideConfig).isFile()) {
console.log(`Load ${overrideConfig}...`);
config = Object.assign(config, require(overrideConfig));
}
} catch (err) {
console.log(`Cannot load ${overrideConfig}.`);
}
}
module.exports = config;
model.js
// scan all models defined in models:
const fs = require('fs');
const db = require('./db');
let files = fs.readdirSync(__dirname + '/models');
let js_files = files.filter((f)=>{
return f.endsWith('.js');
}, files);
module.exports = {};
for (let f of js_files) {
console.log(`import model from file ${f}...`);
let name = f.substring(0, f.length - 3);
module.exports[name] = require(__dirname + '/models/' + f);
}
module.exports.sync = () => {
return db.sync();
};
init-db.js
const model = require('./model.js');
model.sync().then(()=>{
console.log('sync done');
process.exit(0);
}).catch((e)=>{
console.log('failed with: '+e);
process.exit(0);});
app.js
const model = require('./model');
let
Pet = model.Pet,
User = model.User;
(async () => {
var user = await User.create({
name: 'John',
gender: false,
email: 'john-' + Date.now() + '@garfield.pet',
passwd: 'hahaha'
});
console.log('created: ' + JSON.stringify(user));
var cat = await Pet.create({
ownerId: user.id,
name: 'Garfield',
gender: false,
birth: '2007-07-07',
});
console.log('created: ' + JSON.stringify(cat));
var dog = await Pet.create({
ownerId: user.id,
name: 'Odie',
gender: false,
birth: '2008-08-08',
});
console.log('created: ' + JSON.stringify(dog));
})();
mysql命令:
create database nodejs;
grant all privileges on nodejs.* to 'www'@'%' identified by 'www';
grant all privileges on test.* to 'www'@'%' identified by 'www';
node命令
node init-db.js
node app.js