[轉]Node.JS使用Sequelize操作MySQL


 

 

 

 

本文轉自:https://www.jianshu.com/p/797e10fe2393

Node.JS提供了操作數據庫的基礎接口,我們可以通過mysql模塊的query方法進行操作,但是需要編寫SQL語句,對於SQL語句並不精通的人來說有一定的難度,而且在代碼中保留SQL語句也有一定的危險性。為了方便進行數據庫操作,ORM框架應運而生,Sequelize正是這樣的模塊。

安裝Sequelize

首先,使用cd命令將終端控制台定位到項目的根目錄,然后使用npm安裝:

npm install sequelize --save

安裝mysql2

由於sequelize依賴於mysql2所以也需要安裝mysql2:

npm install mysql2 --save

編寫配置

在項目根目錄新建個“configs”文件夾,在文件夾中新建一個名為“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; 

配置說明

  • dbname: 數據庫名稱
  • uname: 數據庫登錄名
  • upwd: 數據庫登錄密碼
  • host: 數據庫主機
  • port: 數據庫端口,mysql默認是3306
  • dialect: 數據庫類型,這里是mysql
  • pool: 連接池配置

【具體配置詳見MySQL相關的博客】

對sequelize進行簡單封裝

在項目根目錄新建“data”文件夾,在改文件夾中新建“db.js”文件。在db.js中添加以下代碼。

首先,創建sequelize實例:


// 引入模塊 const Sequelize = require('sequelize'); // 讀取配置 const mysqlConfig = require('../configs/mysql-config'); // 根據配置實例化seq var seq = new Sequelize(mysqlConfig.dbname, mysqlConfig.uname, mysqlConfig.upwd, { host: mysqlConfig.host, dialect: mysqlConfig.dialect, pool: mysqlConfig.pool }); 

定義一個defineModel函數用於定義數據模型:


/** * 定義數據模型 * * @param {any} name 模型名稱【數據庫表名】 * @param {any} attributes 數據字段集合 * @returns 數據模型對象 */ 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 }; // 狀態:0表示有效,1表示無效,2表示已刪除,默認為0. attrs.status = { type: Sequelize.INTEGER, allowNull: false }; // 調用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; } } } }); } 

在這里我們可以對模型定義做一些修改,比如添加id、createAt、updateAt、version和status字段等。這樣,通過這個函數定義的模型都會帶這幾個字段,通常一個數據庫表都應該包含這些字段。

sequelize默認會為模型添加id字段,自增,主鍵。所以在這里可以不用關心該字段的定義。

在調用seq.define()方法的時候,設置了“timestamps”為false,當timestamps為true時,默認會為模型添加createAt和updateAt兩個字段,數據類型為Sequelize.DATE,這里我們自己定義為Sequelize.BIGINT用於存儲時間戳。

同時,設置tableName和模型的名稱一致,這樣符合我們的慣性思維。

最后,db.js模塊導出defineModel函數:


exports.defineModel = defineModel; 

定義模型

在data目錄下新建“model”文件夾,並在model文件夾中添加“Notices.js”。在Notices中,先引入需要的模塊:

var db = require('../db'); var seq = require('sequelize'); 

然后定義數據模型對象:


var Model = db.defineModel('Notices', { content: seq.TEXT, title: seq.STRING(30), startDate: seq.BIGINT, expireDate: seq.BIGINT, gmId: seq.INTEGER(10), }); // 導出模型對象 module.exports = Model; 

引入的db模塊就是前面對sequelize的封裝,然后通過defineModel()函數定義模型,添加公共字段。

在這里引入sequelize模塊主要是為了定義模型的時候指定數據類型。

同步數據結構到數據庫

當模型定義后,需要在數據庫中建立對應的數據表,這時候需要做結構的同步,可以使用以下方法進行同步:

Model.sync(); 

如果數據庫中已經存在該模型對應的表,則不會進行同步操作,如果想要強制進行數據結構的同步,可以通過force參數指定:

Model.sync({force: true}); 

使用模型

在Notices.js文件中可以直接使用Model對象進行操作,如果是外部文件,需要先引入Notices模塊

var Notices = require('../data/model/Notices'); 

添加數據

通過數據模型對象的create方法可以添加一條數據,方法的返回值是一個Promise對象,所以可以直接調用Promise對象的then方法進行后續操作。


Notices.create({
    content: '我是公告內容。', title: '系統公告的標題', gmId: '10086', status: 0, expireDate: 1527396599123, startDate: Date.now() }).then((data) => { res.json({ code: 0, msg: '公告發布成功', result: data }); }); 

then方法的參數是一個function對象,該function對象有一個data參數,這個data參數就是前面create方法操作的數據對象,可以從data里面獲得數據在數據庫中的id是什么。

通過await和async來實現同步編程效果

通過then的方式很像是嵌套function的回調式異步編程,有些有不喜歡嵌套function的人可以采用await來實現同步編程的效果,更多關於await的用法這里不討論。


(async () => { var data = await Notices.create({ content: '我是公告內容。', title: '系統公告的標題', gmId: '10086', status: 0, expireDate: 1527396599123, startDate: Date.now() }); res.json({ code: 0, msg: '公告發布成功', result: data }); })(); 

await修飾的函數調用必須寫在async修改的函數里面,否則會報錯,所以這里在最外層包了一個即時函數。

關於即時函數的概念可以參考《JavaScript面向對象編程指南》這本書,里面說的挺詳細的。簡單說就是定義后立刻調用的一個函數。

修改數據

使用模型對象的update方法可以修改數據:


Notices.update({ status: 2 }, { where: {id: 100} }); 

updata(values, opts)方法的第一個參數是要修改的數據集合,字段名稱和數據表對應。第二個參數是相關的一些操作參數,where用於限制修改的數據的條件,和SQL語句的where作用一樣。

上面的效果是修改id為100的數據的status字段的值為2。

查詢數據

通過數據模型對象的find相關的方法可以實現查詢效果:

查詢所有數據


Notices.findAll(); 

改方法會返回Notices表中所有的數據,返回值依然是一個Promise對象。

條件查詢


Notices.findAll({order: [['createAt', 'DESC']], limit: 10, where: {'status': 0}}); 
  • order字段用於指定排序規則,這里指定以createAt字段做降序排序。
  • limit字段用於指定查詢的數據量,這里表示返回前10條數據。
  • where字段用於指定條件查詢,這里表示查詢status為0的數據。

刪除數據

通過數據模型對象的destroy方法可以銷毀一條數據,具體用法和查詢、修改等類似。

但是通常我們做刪除操作的時候並不是真的將數據從數據庫中抹除,而是通過數據的狀態字段去標識,方便后續維護。所以每個表通常都會定義一個status字段。

復雜的where條件

在sequelize中,還存在一個Op對象,用於處理復雜的條件操作。

[案例一]

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。修改的條件的,數據的id字段必須是在[1, 4, 2, 8, 13, 20]這個數組中的數據。

[案例二]


var date = Date.now(); Model.findAll({ where: { status: 0, sendDate: {[Op.lte]: date}, expireDate: {[Op.gte]: date}, [Op.or]: [ {to: 1000017}, {to: 0} ] } }); 

上面這段代碼表示查詢所有sendDate小於等於當前時間,並且expireDate大於等於當前時間,且status的值為0,並且to字段的值為1000017或者為0。

參考文檔

以上也只是舉了一部分例子進行簡單說明而已,詳細的可以查考這份文檔,雖然是英文的,但是稍微花點時間應該多少是可以看懂的。

http://docs.sequelizejs.com/identifiers.html

【寫在文末:ORM方便了數據庫的操作,但是對於很多復雜的業務,它可能也並不能很好的解決,所以某些特定需求還是需要SQL來實現。】



作者:曾彬思
鏈接:https://www.jianshu.com/p/797e10fe2393
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM