Nodejs ORM框架Sequelize(模型,關聯表,事務,迴圈,及常見問題)
阿新 • • 發佈:2019-01-04
1.建立連線
const Sequelize = require('sequelize'); const sequelize = new Sequelize('database', 'username', 'password', { host: 'host', port: 'port', pool: { max: 50, min: 0, //建立連線最長時間 acquire: 30000, //空閒最長連線時間 idle: 10000 }, //預設輸出執行sql語句 logging: console.log, define: { //預設建立表有 createAt, updateAt timestamps: false, //可以給表設定別名 freezeTableName: true, // 欄位以下劃線(_)來分割(預設是駝峰命名風格) underscored: false }, //sequelize v4 必須設定方言 dialect: 'mysql', //預設DECIMAL and NEWDECIMAL 返回 String dialectOptions: { decimalNumbers: true }, //設定別名,否則不識別$like等關鍵詞($like: Op.like對應關係) operatorsAliases: 'object', //時間上的統一 timezone: "+08:00", })
2.模型定義
const DataTypes = Sequelize.DataTypes; const user = sequelize.define('u', { userId: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, userName: { type: DataTypes.STRING, allowNull: true }, birthDay: { type: 'TIMESTAMP', allowNull: false }, gender: { type: DataTypes.INTEGER, allowNull: true, defaultValue: 0 }, ctime: { type: 'TIMESTAMP', allowNull: false, defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') }, updatedAt: { type: 'TIMESTAMP', defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), field: 'ctime' } }, { tableName: 'user' }) const products = sequelize.define('p', { prdId: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true }, prdName: { type: DataTypes.STRING, allowNull: false }, userId: { type: DataTypes.INTEGER, allowNull: false }, price: { type: DataTypes.DECIMAL(5, 4), allowNull: false } }) products.belongsTo(user, { foreignKey: 'userId', targetKey: 'userId', as: 'u' });
注意點:
1. type如果不存在則直接用字串表示 如:’TIMESTAMP’;
2. 如果需要在更新表字段時記錄更新時間,可應使用updateAt,並設定預設值和對應的欄位名。
3. 如果預設值不是具體的數值,可以用literal函式去表示。
4. tableName 表名, u為別名。
5. 建立關聯關係時,如果外來鍵關聯的是主鍵則不用寫targetKey,否則需要。
3.查詢資料
products.findAll({ attributes: ['prdName', 'price'], include: [{ model: user, as: 'u', attributes: ['userName'] }], //raw:true }).then(result => { console.log(JSON.stringify(result)) }).catch(err => { console.log(err) })
//結果1:
[
{
"prdName": "ipad",
"price": 4.99,
"u": { "userName": "張三" }
},
{
"prdName": "iphone",
"price": 3.658,
"u": { "userName": "張三" }
},
{
"prdName": "聯想筆記本",
"price": 9.32,
"u": { "userName": "李四" }
}
]
我們換個寫法
products.findAll({
attributes: ['prdName', 'price'],
include: [{
model: user,
as: 'u',
attributes: ['userName']
}],
raw:true
}).then(result => {
console.log(JSON.stringify(result))
}).catch(err => {
console.log(err)
})
結果2
[
{
"prdName":"ipad",
"price":4.99,
"u.userName":"張三"
},
{
"prdName":"iphone",
"price":3.658,
"u.userName":"張三"
},
{
"prdName":"聯想筆記本",
"price":9.32,
"u.userName":"李四"
}
]
換個寫法
products.findAll({
attributes: [Sequelize.col('u.userName'),'prdName', 'price'],
include: [{
model: user,
as: 'u',
attributes: []
}],
raw:true
}).then(result => {
console.log(JSON.stringify(result))
}).catch(err => {
console.log(err)
})
結果3:
[
{
"userName":"張三",
"prdName":"ipad",
"price":4.99
},
{
"userName":"張三",
"prdName":"iphone",
"price":3.658
},
{
"userName":"李四",
"prdName":"聯想筆記本",
"price":9.32
}
]
可以看出來結果3是我們想要的結果
加條件的寫法:
products.findAll({
attributes: [Sequelize.col('u.userName'), 'prdName', 'price'],
include: [{
model: user,
as: 'u',
attributes: []
}],
where: {
prdName: 'ipad',
'$u.userId$': 1
},
raw: true
}).then(result => {
console.log(JSON.stringify(result))
}).catch(err => {
console.log(err)
})
對應sql:
SELECT `u`.`userName`, `p`.`prdName`, `p`.`price` FROM `products` AS `p` LEFT OUTER JOIN `user` AS `u` ON `p`.`userId` = `u`.`userId` WHERE `p`.`prdName` = ‘ipad’ AND `u`.`userId` = 1;
如果給include 表加where條件 須使用'$u.userId$'這種寫法;也可在include加where條件
4.事務
function doit() {
//啟用事務(自動提交)
return sequelize.transaction(function (t) {
return user.create({
userName: '黃曉明',
birthDay: '1991-06-23',
gender: 0
}, {
transaction: t
}).then(result => {
return user.update({
userName: '李四',
}, {
where: { userId: result.userId },
transaction: t //注意(事務transaction 須和where同級)second parameter is "options", so transaction must be in it
})
})
}).then(result => {
// Transaction 會自動提交
// result 是事務回撥中使用promise鏈中執行結果
// console.log(result.length)
console.log("ok")
}).catch(err => {
// Transaction 會自動回滾
// err 是事務回撥中使用promise鏈中的異常結果
console.log(err)
})
}
5. 迴圈
const Op = Sequelize.Op;
const Promise = require('bluebird');
function recycle() {
let tranArray = [];
products.findAll({
attributes: ['prdId', 'prdName', 'userId', 'price'],
raw: true
}).then(result => {
result.forEach(rec => {
tranArray.push(products.create({
prdName: rec.prdName,
userId: rec.userId,
price: rec.price
}))
})
return Promise.all(tranArray)
}).then(result => {
console.log('result' + result)
}).catch(err => {
console.log('err' + err)
})
}
一般配合事務使用。