新聞中心
Node.JS提供了操作數(shù)據(jù)庫(kù)的基礎(chǔ)接口,我們可以通過(guò)MySQL模塊的query方法進(jìn)行操作,但是需要編寫(xiě)SQL語(yǔ)句,對(duì)于SQL語(yǔ)句并不精通的人來(lái)說(shuō)有一定的難度,而且在代碼中保留SQL語(yǔ)句也有一定的危險(xiǎn)性。為了方便進(jìn)行數(shù)據(jù)庫(kù)操作,ORM框架應(yīng)運(yùn)而生,Sequelize正是這樣的模塊。
成都創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都做網(wǎng)站、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的蘭山網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
安裝Sequelize
首先,使用cd命令將終端控制臺(tái)定位到項(xiàng)目的根目錄,然后使用npm安裝:
npm install sequelize --save
安裝mysql2
由于sequelize依賴(lài)于mysql2所以也需要安裝mysql2:
npm install mysql2 --save
編寫(xiě)配置
在項(xiàng)目根目錄新建個(gè)“configs”文件夾,在文件夾中新建一個(gè)名為“mysql-config.js”的文件,代碼如下:
var config = { dbname: 'testdb', uname: 'root', upwd: 'root', host: 'localhost', port: 3306, dialect: 'mysql', pool: { max: 5, min: 0, idle: 10000 } }; module.exports = config;
配置說(shuō)明
- dbname: 數(shù)據(jù)庫(kù)名稱(chēng)
- uname: 數(shù)據(jù)庫(kù)登錄名
- upwd: 數(shù)據(jù)庫(kù)登錄密碼
- host: 數(shù)據(jù)庫(kù)主機(jī)
- port: 數(shù)據(jù)庫(kù)端口,mysql默認(rèn)是3306
- dialect: 數(shù)據(jù)庫(kù)類(lèi)型,這里是mysql
- pool: 連接池配置
【具體配置詳見(jiàn)MySQL相關(guān)的博客】
對(duì)sequelize進(jìn)行簡(jiǎn)單封裝
在項(xiàng)目根目錄新建“data”文件夾,在改文件夾中新建“db.js”文件。在db.js中添加以下代碼。
首先,創(chuàng)建sequelize實(shí)例:
// 引入模塊 const Sequelize = require('sequelize'); // 讀取配置 const mysqlConfig = require('../configs/mysql-config'); // 根據(jù)配置實(shí)例化seq var seq = new Sequelize(mysqlConfig.dbname, mysqlConfig.uname, mysqlConfig.upwd, { host: mysqlConfig.host, dialect: mysqlConfig.dialect, pool: mysqlConfig.pool });
定義一個(gè)defineModel函數(shù)用于定義數(shù)據(jù)模型:
/** * 定義數(shù)據(jù)模型 * * @param {any} name 模型名稱(chēng)【數(shù)據(jù)庫(kù)表名】 * @param {any} attributes 數(shù)據(jù)字段集合 * @returns 數(shù)據(jù)模型對(duì)象 */ 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.createAt = { type: Sequelize.BIGINT, allowNull: false }; attrs.updateAt = { type: Sequelize.BIGINT, allowNull: false }; attrs.version = { type: Sequelize.BIGINT, allowNull: false }; // 狀態(tài):0表示有效,1表示無(wú)效,2表示已刪除,默認(rèn)為0. attrs.status = { type: Sequelize.INTEGER, allowNull: false }; // 調(diào)用seq的方法定義模型并返回 return seq.define(name, attrs, { tableName: name, timestamps: false, hooks: { beforeValidate: function (obj) { let now = Date.now(); if (obj.isNewRecord) { obj.createAt = now; obj.updateAt = now; obj.version = 0; } else { obj.updateAt = now; ++obj.version; } } } }); }
在這里我們可以對(duì)模型定義做一些修改,比如添加id、createAt、updateAt、version和status字段等。這樣,通過(guò)這個(gè)函數(shù)定義的模型都會(huì)帶這幾個(gè)字段,通常一個(gè)數(shù)據(jù)庫(kù)表都應(yīng)該包含這些字段。
sequelize默認(rèn)會(huì)為模型添加id字段,自增,主鍵。所以在這里可以不用關(guān)心該字段的定義。
在調(diào)用seq.define()方法的時(shí)候,設(shè)置了“timestamps”為false,當(dāng)timestamps為true時(shí),默認(rèn)會(huì)為模型添加createAt和updateAt兩個(gè)字段,數(shù)據(jù)類(lèi)型為Sequelize.DATE,這里我們自己定義為Sequelize.BIGINT用于存儲(chǔ)時(shí)間戳。
同時(shí),設(shè)置tableName和模型的名稱(chēng)一致,這樣符合我們的慣性思維。
最后,db.js模塊導(dǎo)出defineModel函數(shù):
exports.defineModel = defineModel;
定義模型
在data目錄下新建“model”文件夾,并在model文件夾中添加“Notices.js”。在Notices中,先引入需要的模塊:
var db = require('../db'); var seq = require('sequelize');
然后定義數(shù)據(jù)模型對(duì)象:
var Model = db.defineModel('Notices', { content: seq.TEXT, title: seq.STRING(30), startDate: seq.BIGINT, expireDate: seq.BIGINT, gmId: seq.INTEGER(10), }); // 導(dǎo)出模型對(duì)象 module.exports = Model;
引入的db模塊就是前面對(duì)sequelize的封裝,然后通過(guò)defineModel()函數(shù)定義模型,添加公共字段。
在這里引入sequelize模塊主要是為了定義模型的時(shí)候指定數(shù)據(jù)類(lèi)型。
同步數(shù)據(jù)結(jié)構(gòu)到數(shù)據(jù)庫(kù)
當(dāng)模型定義后,需要在數(shù)據(jù)庫(kù)中建立對(duì)應(yīng)的數(shù)據(jù)表,這時(shí)候需要做結(jié)構(gòu)的同步,可以使用以下方法進(jìn)行同步:
Model.sync();
如果數(shù)據(jù)庫(kù)中已經(jīng)存在該模型對(duì)應(yīng)的表,則不會(huì)進(jìn)行同步操作,如果想要強(qiáng)制進(jìn)行數(shù)據(jù)結(jié)構(gòu)的同步,可以通過(guò)force參數(shù)指定:
Model.sync({force: true});
使用模型
在Notices.js文件中可以直接使用Model對(duì)象進(jìn)行操作,如果是外部文件,需要先引入Notices模塊
var Notices = require('../data/model/Notices');
添加數(shù)據(jù)
通過(guò)數(shù)據(jù)模型對(duì)象的create方法可以添加一條數(shù)據(jù),方法的返回值是一個(gè)Promise對(duì)象,所以可以直接調(diào)用Promise對(duì)象的then方法進(jìn)行后續(xù)操作。
Notices.create({ content: '我是公告內(nèi)容。', title: '系統(tǒng)公告的標(biāo)題', gmId: '10086', status: 0, expireDate: 1527396599123, startDate: Date.now() }).then((data) => { res.json({ code: 0, msg: '公告發(fā)布成功', result: data }); });
then方法的參數(shù)是一個(gè)function對(duì)象,該function對(duì)象有一個(gè)data參數(shù),這個(gè)data參數(shù)就是前面create方法操作的數(shù)據(jù)對(duì)象,可以從data里面獲得數(shù)據(jù)在數(shù)據(jù)庫(kù)中的id是什么。
通過(guò)await和async來(lái)實(shí)現(xiàn)同步編程效果
通過(guò)then的方式很像是嵌套function的回調(diào)式異步編程,有些有不喜歡嵌套function的人可以采用await來(lái)實(shí)現(xiàn)同步編程的效果,更多關(guān)于await的用法這里不討論。
(async () => { var data = await Notices.create({ content: '我是公告內(nèi)容。', title: '系統(tǒng)公告的標(biāo)題', gmId: '10086', status: 0, expireDate: 1527396599123, startDate: Date.now() }); res.json({ code: 0, msg: '公告發(fā)布成功', result: data }); })();
await修飾的函數(shù)調(diào)用必須寫(xiě)在async修改的函數(shù)里面,否則會(huì)報(bào)錯(cuò),所以這里在最外層包了一個(gè)即時(shí)函數(shù)。
關(guān)于即時(shí)函數(shù)的概念可以參考《JavaScript面向?qū)ο缶幊讨改稀愤@本書(shū),里面說(shuō)的挺詳細(xì)的。簡(jiǎn)單說(shuō)就是定義后立刻調(diào)用的一個(gè)函數(shù)。
修改數(shù)據(jù)
使用模型對(duì)象的update方法可以修改數(shù)據(jù):
Notices.update({ status: 2 }, { where: {id: 100} });
updata(values, opts)方法的第一個(gè)參數(shù)是要修改的數(shù)據(jù)集合,字段名稱(chēng)和數(shù)據(jù)表對(duì)應(yīng)。第二個(gè)參數(shù)是相關(guān)的一些操作參數(shù),where用于限制修改的數(shù)據(jù)的條件,和SQL語(yǔ)句的where作用一樣。
上面的效果是修改id為100的數(shù)據(jù)的status字段的值為2。
查詢數(shù)據(jù)
通過(guò)數(shù)據(jù)模型對(duì)象的find相關(guān)的方法可以實(shí)現(xiàn)查詢效果:
查詢所有數(shù)據(jù)
Notices.findAll();
改方法會(huì)返回Notices表中所有的數(shù)據(jù),返回值依然是一個(gè)Promise對(duì)象。
條件查詢
Notices.findAll({order: [['createAt', 'DESC']], limit: 10, where: {'status': 0}});
- order字段用于指定排序規(guī)則,這里指定以createAt字段做降序排序。
- limit字段用于指定查詢的數(shù)據(jù)量,這里表示返回前10條數(shù)據(jù)。
- where字段用于指定條件查詢,這里表示查詢status為0的數(shù)據(jù)。
刪除數(shù)據(jù)
通過(guò)數(shù)據(jù)模型對(duì)象的destroy方法可以銷(xiāo)毀一條數(shù)據(jù),具體用法和查詢、修改等類(lèi)似。
但是通常我們做刪除操作的時(shí)候并不是真的將數(shù)據(jù)從數(shù)據(jù)庫(kù)中抹除,而是通過(guò)數(shù)據(jù)的狀態(tài)字段去標(biāo)識(shí),方便后續(xù)維護(hù)。所以每個(gè)表通常都會(huì)定義一個(gè)status字段。
復(fù)雜的where條件
在sequelize中,還存在一個(gè)Op對(duì)象,用于處理復(fù)雜的條件操作。
[案例一]
var seq = require('sequelize'); var Op = seq.Op; // 其它代碼... Model.update({ status: 2, gmId: 10086 }, { where: { id: { [Op.in]: [1, 4, 2, 8, 13, 20] } } });
上面這段代碼表示修改status的值為2,修改gmId的值為10086。修改的條件的,數(shù)據(jù)的id字段必須是在[1, 4, 2, 8, 13, 20]這個(gè)數(shù)組中的數(shù)據(jù)。
[案例二]
var date = Date.now(); Model.findAll({ where: { status: 0, sendDate: {[Op.lte]: date}, expireDate: {[Op.gte]: date}, [Op.or]: [ {to: 1000017}, {to: 0} ] } });
上面這段代碼表示查詢所有sendDate小于等于當(dāng)前時(shí)間,并且expireDate大于等于當(dāng)前時(shí)間,且status的值為0,并且to字段的值為1000017或者為0。
參考文檔
以上也只是舉了一部分例子進(jìn)行簡(jiǎn)單說(shuō)明而已,詳細(xì)的可以查考這份文檔,雖然是英文的,但是稍微花點(diǎn)時(shí)間應(yīng)該多少是可以看懂的。
http://docs.sequelizejs.com/identifiers.html
【寫(xiě)在文末:ORM方便了數(shù)據(jù)庫(kù)的操作,但是對(duì)于很多復(fù)雜的業(yè)務(wù),它可能也并不能很好的解決,所以某些特定需求還是需要SQL來(lái)實(shí)現(xiàn)?!?/p>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
網(wǎng)站標(biāo)題:Node.JS使用Sequelize操作MySQL的示例代碼
分享網(wǎng)址:http://www.dlmjj.cn/article/pgodpi.html