NodeJS ORM 框架 Sequelize 操作數(shù)據(jù)庫(kù)小結(jié)

2017年8月10日20:12:20 Edit By K

簡(jiǎn)介

Sequelize 是一個(gè) Node.js 平臺(tái)基于Promise 的 ORM[1]声搁∈勇可以操作管理 Mysql一罩、Postgres莉测、SQLite 等關(guān)系型數(shù)據(jù)庫(kù)。

Sequelize 文檔 http://docs.sequelizejs.com/en/latest/

安裝

創(chuàng)建 NodeJs 項(xiàng)目

$ mkdir YourDirName
$ cd YourDirName
$ npm init

安裝 Sequelize 和 Mysql 包

$ npm install sequelize --save
$ npm install mysql --save

至此柔袁,安裝結(jié)束呆躲。

當(dāng)然我給你們發(fā)的包已經(jīng)創(chuàng)建好了 Node Express 項(xiàng)目及相關(guān)依賴,不必再安裝一遍捶索。

如果你想自己再試試的話歼秽,建議參考 Sequelize 官方文檔,如果沒(méi)記錯(cuò)的話情组,我當(dāng)時(shí)安裝的 Mysql 包是 mysql2。

$ npm install mysql2

兩者有沒(méi)有區(qū)別暫時(shí)還沒(méi)查箩祥,有興趣可以自行查一查院崇。

在我發(fā)給你們的項(xiàng)目中還有一些其他依賴包,類似于 BodyParser 等等袍祖,這些包可以在項(xiàng)目的 package.json文件中找到底瓣。

來(lái)吧,操作數(shù)據(jù)庫(kù)蕉陋,造作吧

你需要一個(gè)數(shù)據(jù)庫(kù)

操作數(shù)據(jù)庫(kù)捐凭,沒(méi)有數(shù)據(jù)庫(kù)怎么行呢?首先我們要?jiǎng)?chuàng)建一個(gè) database凳鬓。

我發(fā)給大家的項(xiàng)目里數(shù)據(jù)庫(kù)名稱是 getitmore茁肠,請(qǐng)?jiān)?Mysql 中創(chuàng)建好。

在創(chuàng)建數(shù)據(jù)庫(kù)的時(shí)候缩举,推薦選擇編碼 UTF-8垦梆,畢竟國(guó)際通用

我平時(shí)管理數(shù)據(jù)庫(kù)的軟件是 Navicat Premium,不再安利它了

連接真的如此簡(jiǎn)單

Sequelize 提供了多種多樣的連接方式仅孩,官網(wǎng)給出了如下幾種:

/*** 分別介紹一下連接方式 ***/
var sequelize = new Sequelize(database, [username=null], [password=null], [options={}]);
// 沒(méi)有密碼和 options 的情況
var sequelize = new Sequelize('database', 'username');
// 沒(méi)有options 的情況
var sequelize = new Sequelize('database', 'username', 'password');
// 沒(méi)有密碼托猩,有 options 的情況
var sequelize = new Sequelize('database', 'username', null, {});
// 啥都有的情況
var sequelize = new Sequelize('databse', 'username', 'password', {});
// 舉個(gè)沒(méi)有用戶名密碼和 options 的小栗子
var sequelize = new Sequelize('mysql://localhost:3306/databse', {});

/*** 下面這種方式適用于生產(chǎn)環(huán)境,推薦 ***/
var sequelize = new Sequelize('database', 'root', 'root', {
  host: 'localhost',    // 數(shù)據(jù)庫(kù)地址
  dialect: 'mysql',     // 數(shù)據(jù)庫(kù)類型
  pool: {
    max: 5,             // 連接池最大連接數(shù)量
    min: 0,             // 連接池最小連接數(shù)量
    idle: 10000         // 如果一個(gè)線程超過(guò)10秒鐘沒(méi)有被使用過(guò)就釋放該線程
  }
})

我們項(xiàng)目采用的即時(shí)最后一種連接池的方式辽慕,連接時(shí) Sequelize 會(huì)設(shè)置一個(gè)連接池京腥,我們?cè)谑褂玫臅r(shí)候只需要實(shí)例化一個(gè)就行[2]

在項(xiàng)目中我創(chuàng)建了如下文件/controller/db.js以供配置數(shù)據(jù)庫(kù)使用:

/**
 * Created by K on 2017-07-31.
 */

var Sequelize = require("sequelize");

/**
 * 連接指定類型的數(shù)據(jù)庫(kù)
 * host:數(shù)據(jù)庫(kù)地址
 * max:連接池最大連接數(shù)量
 * min:連接池最小連接數(shù)量
 * idle:每個(gè)線程最長(zhǎng)等待時(shí)間
 * @type {Sequelize}
 */
module.exports = new Sequelize('getitmore', 'root', 'root', {
    host: 'localhost',
    dialect: 'mysql',
    pool: {
        max: 20,
        min: 0,
        idle: 10000
    }
});

映射數(shù)據(jù)表

ORM 的思想是什么,映射成對(duì)象啊溅蛉,映射 Sql 語(yǔ)句啊公浪。好的他宛,我們來(lái)看看 Sequelize 怎么映射的吧。

/*** 舉個(gè)小栗子 user.js ***/
// 引入 sequelize 包因悲,創(chuàng)建 sequelize 實(shí)例
let Sequelize = require('sequelize');
let sequelize = require('./db.js');

// 創(chuàng)建 Model
let User = sequelize.define('user', {
  // 指定映射的字段類型堕汞,字段名,例如數(shù)據(jù)庫(kù)中 user 表中的 username 字段映射成 username
  username: {
    type: Sequelize.STRING,
    field: 'username'
  },
  // 如果不指定 field晃琳,會(huì)自動(dòng)映射相同名稱的字段
  email: {
    type: Sequelize.STRING
  }
}, {
  // freezeTabelName 為 true 時(shí)不會(huì)在庫(kù)中映射表時(shí)增加復(fù)數(shù)表名
  // 該選項(xiàng)為 true 時(shí)讯检,user 在映射時(shí)映射成 user,而為 false 時(shí)會(huì)映射成users
  freezeTableName: false
});

// 創(chuàng)建或同步表
// User.sync() 會(huì)返回一個(gè) Promise 對(duì)象
// force = true 時(shí)會(huì)把存在的表先 drop 掉再創(chuàng)建卫旱,好怕怕
let user = User.sync({ force: false});

// 現(xiàn)在可以操作 User 執(zhí)行增刪改查啦
// 舉兩個(gè)栗子
// 添加用戶
exports.addUser = function(username, email) {
  return User.create({
    username: username,
    email: email
  })
};
// 查找用戶
exports.findUserByName = function(username) {
  return User.findOne({
    where: {
      username: username
    }
  })
};

以上是一個(gè)不那么完整的 Demo人灼,在我們項(xiàng)目中還有很多 options 需要設(shè)置,還有很多 Sequelize 的方法顾翼,遠(yuǎn)不止 create()findOne()這么簡(jiǎn)單投放,字段類也遠(yuǎn)不止STRING這一種。來(lái)看一個(gè)咱們項(xiàng)目中的 Model适贸,以原創(chuàng)表為栗子:

/**
 * Created by kk on 2017/8/1.
 */

let Sequelize = require('sequelize');
let sequelize = require('../controller/db');

/**
 * 定義原創(chuàng) Model
 * 包括五個(gè)屬性 title灸芳、content、content_detail拜姿、img_url烙样、count、create_time
 * freezeTableName 表示是否在數(shù)據(jù)庫(kù)中創(chuàng)建復(fù)數(shù)表名蕊肥,例如 users
 * timestamp 表示是否在數(shù)據(jù)庫(kù)中創(chuàng)建 createAt 和 updateAt 字段
 */
let Original = sequelize.define('original', {
    title: { type: Sequelize.STRING },
    content: { type: Sequelize.STRING },
    content_detail: { type: Sequelize.TEXT('long') },
    img_url: { type: Sequelize.STRING },
    count: { type: Sequelize.INTEGER },
    create_time: { type: Sequelize.DATE }
}, {
    freezeTableName: true,
    timestamps: false
});

// 創(chuàng)建表谒获,force 為 true 時(shí)會(huì)先執(zhí)行 drop 再創(chuàng)建
let original = Original.sync({ force: false});

// 分頁(yè)獲取原創(chuàng)
exports.findOriginalPageList = function(pageNo, limit) {
    console.log(pageNo);
    return Original.findAll({
        limit: limit,
        offset: pageNo
    });
};

// 根據(jù)id獲取原創(chuàng)詳細(xì)內(nèi)容
exports.findOriginalById = function(originalId) {
    return Original.findById(originalId);
};

// 根據(jù)Id列表獲取原創(chuàng)
exports.findOriginalByIdList = function(originalIdList) {
    return Original.findAll({
        where: {
            id: originalIdList
        }
    })
};

我為了讓項(xiàng)目顯得結(jié)構(gòu)清楚,創(chuàng)建了 Model 的文件夾壁却,所有映射的數(shù)據(jù)表都在該文件夾下批狱。當(dāng)然,我們項(xiàng)目中的栗子也不能囊括所有的 Sequelize 用法展东,最好的方式還是去看官網(wǎng)文檔赔硫。

啊盐肃?返回的是什么卦停,我怎么取值啊恼蓬?

來(lái)創(chuàng)建一個(gè)測(cè)試腳本看看它到底返回了一個(gè)什么惊完!

// test.js
var user = require('./user');
user.addUser('test', 'works@163.com').then(function() {
  return user.findByName('test');
}).then(function(user) {
  console.log('這里的 user 就是在執(zhí)行完 findByName 之后返回的對(duì)象');
  console.log('username:' + user.username);
  console.log('email:' + user.email);
})

至此,一個(gè)基本的數(shù)據(jù)庫(kù)操作就完成了处硬。執(zhí)行以下試試看:

$ node test.js

驚不驚喜小槐?意不意外?

注意

以上我介紹的 Sequelize 操作目錄結(jié)構(gòu)如下:

  • YourDirName
    • db.js
    • user.js
    • test.js

咱們項(xiàng)目的結(jié)構(gòu)我進(jìn)行了調(diào)整,將 controller凿跳、model件豌、和 view 進(jìn)行了人為劃分:

  • NodeExpressServer
    • controller
      • db.js
    • model
      • extra.js
      • collect.js
      • user.js
      • ...
    • app.js

至此,還有什么問(wèn)題的話控嗜,問(wèn)我吧茧彤,向我開(kāi)炮吧。

說(shuō)句題外話疆栏,看看我寫的代碼是不是非常優(yōu)雅曾掂,哈哈哈,學(xué)著點(diǎn)

變量名壁顶,換行珠洗,空格的設(shè)置,整齊劃一的風(fēng)格若专,堅(jiān)持是一種信仰许蓖,習(xí)慣也不是一天養(yǎng)成的,推薦一本書(shū)《代碼整潔之道》

記椎魉ァ:你本來(lái)就很美膊爪。

安利這款新 Markdown 編輯器:Typora


  1. ORM 和 Promise 的概念自行查找 ?

  2. 連接池的概念不理解的話自行度娘 or Google ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嚎莉,隨后出現(xiàn)的幾起案子蚁飒,更是在濱河造成了極大的恐慌,老刑警劉巖萝喘,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異琼懊,居然都是意外死亡阁簸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門哼丈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)启妹,“玉大人,你說(shuō)我怎么就攤上這事醉旦∪拿祝” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵车胡,是天一觀的道長(zhǎng)檬输。 經(jīng)常有香客問(wèn)我,道長(zhǎng)匈棘,這世上最難降的妖魔是什么丧慈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上逃默,老公的妹妹穿的比我還像新娘鹃愤。我一直安慰自己,他們只是感情好完域,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布软吐。 她就那樣靜靜地躺著,像睡著了一般吟税。 火紅的嫁衣襯著肌膚如雪凹耙。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天乌妙,我揣著相機(jī)與錄音使兔,去河邊找鬼。 笑死藤韵,一個(gè)胖子當(dāng)著我的面吹牛虐沥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播泽艘,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼欲险,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了匹涮?” 一聲冷哼從身側(cè)響起天试,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎然低,沒(méi)想到半個(gè)月后喜每,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雳攘,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年带兜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吨灭。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡刚照,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出喧兄,到底是詐尸還是另有隱情无畔,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布吠冤,位于F島的核電站浑彰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拯辙。R本人自食惡果不足惜闸昨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧饵较,春花似錦拍嵌、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至茄猫,卻和暖如春狈蚤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背划纽。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工脆侮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人勇劣。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓靖避,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親比默。 傳聞我的和親對(duì)象是個(gè)殘疾皇子幻捏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,498評(píng)論 25 707
  • # Python 資源大全中文版 我想很多程序員應(yīng)該記得 GitHub 上有一個(gè) Awesome - XXX 系列...
    aimaile閱讀 26,441評(píng)論 6 428
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,748評(píng)論 6 342
  • 人總是等到失去才懂得珍惜,奶奶已經(jīng)去世了命咐,才懂得她的存在之于我有多么珍貴的意義篡九,這輩子再也見(jiàn)不到你了,每次回家你都...
    陌暮閱讀 165評(píng)論 0 2
  • 我們時(shí)常會(huì)聽(tīng)到一些尷尬的事情,在健身圈里也堅(jiān)持會(huì)有比較尷尬的問(wèn)題窜司,今天帶大家感受感受沛善。 我一周五次健身房,周六周日...
    91運(yùn)動(dòng)聯(lián)盟官方閱讀 361評(píng)論 0 2