Egg 框架簡述 (三):持久層方案

Egg 框架模型簡述 (三)

  1. 簡單的骨架認(rèn)知
  2. 插件使用(Plugins)
  3. 持久層方案(egg-sequelize)
  4. Worker 和 高效負(fù)載均衡
  5. Agent 代理角色
  6. 定時(shí)任務(wù)

筆者的其他文章推薦: 《JS 函數(shù)式編程思維簡述》

3. 持久層方案(egg-sequelize)

官方文檔:https://eggjs.org

? ? ? ?二維表是一種非常容易描述對(duì)象狀態(tài)的結(jié)構(gòu)倒槐,比如我們有一些寵物小精靈的數(shù)據(jù)需要操作:

image

他們?cè)跀?shù)據(jù)表中大概長這個(gè)樣子:

id name type level prob createdAt
001 妙蛙種子 草,毒 1 46.2% 2018-12-12 10 : 23 : 55
006 噴火龍 火,飛行 3 12.6% 2018-12-03 13 : 02 : 23
054 可達(dá)鴨 水,超能 1 21.7% 2018-11-11 21 : 57 : 06
... ... ... ... ... ...

了解面向?qū)ο蟮耐瑢W(xué)都知道,類型(class)對(duì)實(shí)例(instance)而言起到了規(guī)范和約束的作用绰姻。對(duì)于二維表的設(shè)計(jì)結(jié)構(gòu)衫哥,我們也可以將其類比做一種類型建模胚泌,每一條數(shù)據(jù)都可以當(dāng)作是該類型約束下的一個(gè)實(shí)際的用例。對(duì)這樣的用例數(shù)據(jù),我們最常使用的操作便是 CRUD (數(shù)據(jù)新增鱼响、查詢、修改和刪除)组底。

應(yīng)用中操作數(shù)據(jù)的方式

? ? ? ?我們?cè)趹?yīng)用中丈积,通常通過兩種方式對(duì)數(shù)據(jù)進(jìn)行操作:直接使用結(jié)構(gòu)化查詢語言(SQL) 以及 使用數(shù)據(jù)對(duì)象模型。二者的差異是:

操作 優(yōu)勢 劣勢
SQL查詢 操作靈活债鸡,利于優(yōu)化執(zhí)行過程 硬編碼江滨,不利于擴(kuò)展,對(duì)開發(fā)人員要求高
對(duì)象操作 擴(kuò)展性強(qiáng)厌均,不關(guān)注持久層類型 學(xué)習(xí)成本提升唬滑,使用框架的數(shù)據(jù)操作優(yōu)化方案,靈活性較弱

在項(xiàng)目實(shí)際應(yīng)用過程中棺弊,普遍會(huì)采用后者晶密,以操作數(shù)據(jù)對(duì)象模型的方式,對(duì)數(shù)據(jù)庫進(jìn)行操作镊屎。隨著時(shí)間推移惹挟,也衍生出了一些綜合平衡二者優(yōu)劣勢的折中型持久層數(shù)據(jù)操作方案(被稱之為是半自動(dòng)化):既可以通過SQL的方式編寫操作命令,又能夠由框架解析應(yīng)用層的對(duì)象模型缝驳,進(jìn)行操作處理连锯。

Egg 的選擇

Sequelize 中文API:https://itbilu.com/nodejs/npm/VkYIaRPz-.html#api-instance-models

? ? ? ?在 Node.js 社區(qū)存在著許多 ORM (對(duì)象關(guān)系映射) 框架,其中 Sequelize 便是一個(gè)使用廣泛用狱,支持 MySQL运怖、PostgreSQL、SQLite 和 MSSQL 等多個(gè)數(shù)據(jù)源的優(yōu)秀框架夏伊。
? ? ? ?Sequelize 支持通過數(shù)據(jù)模型對(duì)象來操作持久層摇展,亦支持原始的查詢語句操作。對(duì)于 Egg 而言溺忧,Sequelize 是以插件的方式引入應(yīng)用的咏连,在引入之后盯孙,他會(huì)在創(chuàng)建一個(gè)基本數(shù)據(jù)模型對(duì)象 Model, 并掛載到 appctx 對(duì)象上,以便于使用祟滴≌穸瑁基本上我們需要遵循如下步驟:

image

注意,在真實(shí)的項(xiàng)目中我們需要考慮更多關(guān)于數(shù)據(jù)應(yīng)用環(huán)境以及數(shù)據(jù)遷移垄懂、升降級(jí)骑晶。此時(shí)我們應(yīng)在 配置插件 之后,進(jìn)行詳細(xì)的 Migrations 配置草慧,可參考:https://eggjs.org/zh-cn/tutorials/sequelize.html#初始化數(shù)據(jù)庫和-migrations

使用步驟一:安裝插件 ( 示例基于mysql數(shù)據(jù)庫 )

安裝 egg-sequelizemysql2 插件桶蛔,插件在提供 Sequelize 能力的同時(shí),會(huì)將操作對(duì)象進(jìn)行相應(yīng)的掛載漫谷。

$ npm i --save egg-sequelize mysql2

使用步驟二:啟用插件

在項(xiàng)目中的 ./config/plugin.ts 位置仔雷,啟用相應(yīng)的插件。

import { EggPlugin } from 'egg';

const plugin: EggPlugin = {
    
    // 啟用插件: sequelize
    sequelize: {
        enable: true,
        package: 'egg-sequelize',
    },
}

使用步驟三:配置插件

在配置文件 ./config/config.{env}.ts 中抖剿,對(duì)插件進(jìn)行初始化朽寞。

import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg';

export default (appInfo: EggAppInfo) => {
    const config = {} as PowerPartial<EggAppConfig>;
    // 配置 sesquelize 連接項(xiàng)
    config.sequelize = {
      dialect: 'mysql',
      host: '你的IP',
      port: 你的端口號(hào),
      database: '你的數(shù)據(jù)庫',
      username: '你的名字',
      password: '你的密碼',
      timezone: '+08:00', // 東8區(qū)設(shè)置
      pool: { // 連接池
        max: 10,
        min: 1,
        idle: 10000,
      },
      retry: { max: 3 },
    };
    
    return {
        ...config,
    };
}

使用步驟四:創(chuàng)建模型

此時(shí),我們需要根據(jù)數(shù)據(jù)庫中的表模型斩郎,建立相應(yīng)的應(yīng)用對(duì)象模型脑融。我們將對(duì)象模型置于 app/model/ 位置。例如我們上邊的數(shù)據(jù)庫表 pokemon 的對(duì)應(yīng)模型 app/model/pokemon.ts

const moment = require('moment');

export default (app) => {
    const {
        STRING, DATE, NOW, INTEGER,
    } = app.Sequelize;
    
    // 模型函數(shù)返回的對(duì)象缩宜,會(huì)掛載到 Model 對(duì)象上
    const Pokemon = app.model.define('pokemon', {
        id: {
            type: INTEGER,
            autoIncrement: true,
            primaryKey: true,
        },
        name: STRING,
        type: STRING, // 類別的部分實(shí)際上應(yīng)該提取成另一個(gè)單獨(dú)的表進(jìn)行關(guān)系描述
        level: INTEGER,
        prob: STRING,
        // 處理 sequelize 中的時(shí)區(qū)格式化
        createdAt: {
              type: DATE,
              get createdAt() {
                return moment(Pokemon.getDataValue('createdAt')).format('YYYY-MM-DD HH:mm:ss');
              },
              defaultValue: NOW,
        },
    }, {
        tableName: 'pokemon',
        timestamps: false,
    });
    return Pokemon;
};

使用步驟五:開始使用

此時(shí)肘迎,我們便可以在 ControllerService 部分,進(jìn)行數(shù)據(jù)庫操作了锻煌!

// app/service/pokemon.ts
import { Service } from 'egg';

export default class PokemonService extends Service {

    /**
     * 獲取相應(yīng)ID的數(shù)據(jù)
     * @param {*} param0
     */
    public async queryById(id: number) {
        const {ctx} = this;
        return await ctx.model.pokemon.findById( id );
    }
    
    // ...
}

項(xiàng)目目錄結(jié)構(gòu)

自此妓布,我們的項(xiàng)目目錄結(jié)構(gòu)也相應(yīng)有所變化:

// 這是一個(gè) egg 項(xiàng)目的目錄結(jié)構(gòu)
├─ app
│  ├─ controller
│  │   ├─ pokemon.ts
│  │   └─ home.ts
│  ├─ service
│  │   ├─ pokemon.ts
│  │   └─ home.ts
│  ├─ model
│  │   ├─ pokemon.ts
│  │   └─ user.ts
│  ├─ middleware
│  │   └─ xtoken.ts
│  └─ router.ts
├─ config
│  ├─ config.default.ts
│  ├─ config.prod.ts
│  ├─ config.local.ts
│  └─ plugin.ts

而項(xiàng)目應(yīng)用結(jié)構(gòu)也更加明晰了:


image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市宋梧,隨后出現(xiàn)的幾起案子匣沼,更是在濱河造成了極大的恐慌,老刑警劉巖捂龄,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件释涛,死亡現(xiàn)場離奇詭異,居然都是意外死亡倦沧,警方通過查閱死者的電腦和手機(jī)唇撬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來展融,“玉大人窖认,你說我怎么就攤上這事。” “怎么了扑浸?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵烧给,是天一觀的道長。 經(jīng)常有香客問我首装,道長创夜,這世上最難降的妖魔是什么杭跪? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任仙逻,我火速辦了婚禮,結(jié)果婚禮上涧尿,老公的妹妹穿的比我還像新娘系奉。我一直安慰自己,他們只是感情好姑廉,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布缺亮。 她就那樣靜靜地躺著,像睡著了一般桥言。 火紅的嫁衣襯著肌膚如雪萌踱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天号阿,我揣著相機(jī)與錄音并鸵,去河邊找鬼。 笑死扔涧,一個(gè)胖子當(dāng)著我的面吹牛园担,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播枯夜,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼弯汰,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了湖雹?” 一聲冷哼從身側(cè)響起咏闪,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎摔吏,沒想到半個(gè)月后鸽嫂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舔腾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年溪胶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稳诚。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哗脖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情才避,我是刑警寧澤橱夭,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站桑逝,受9級(jí)特大地震影響棘劣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜楞遏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一茬暇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧寡喝,春花似錦糙俗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至格二,卻和暖如春劈彪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背顶猜。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國打工沧奴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恶耽,地道東北人场绿。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像途蒋,于是被迫代替她去往敵國和親抄淑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子屠凶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359