上一篇介紹瞭如何建立項目、路由的訪問以及如何建立模塊,這篇來說講數據庫的鏈接與使用。前端
既然是後端項目,固然要能連上數據庫,不然還不如直接寫靜態頁面。mysql
本教程使用的是 MySQL,有人可能會問爲啥不用 MongoDB。。。呃,由於公司使用 MySQL,我也是結合項目經歷寫的教程,MongoDB 還沒踩過坑,因此就不在這誤人子弟了。git
GitHub 項目地址,歡迎各位大佬 Star。github
首先要確保你有數據庫能夠鏈接,若是沒有,能夠在 MySQL 官網下載一個,本地跑起來。安裝教程這裏就不敘述了,「百度一下,你就知道」。sql
推薦使用 Navicat Premium 可視化工具來管理數據庫。typescript
用 Navicat 鏈接上數據庫後,新建一個庫:數據庫
點開咱們剛建立的庫 nest_zero_to_one
,點開 Tables,發現裏面空空如也,接下來咱們建立一張新表,點開上面工具欄的 Query,並新增查詢:npm
將下列代碼複製到框內,點擊上面的運行,便可完成表的建立:後端
CREATE TABLE `admin_user` ( `user_id` smallint(6) NOT NULL AUTO_INCREMENT COMMENT '用戶ID', `account_name` varchar(24) NOT NULL COMMENT '用戶帳號', `real_name` varchar(20) NOT NULL COMMENT '真實姓名', `passwd` char(32) NOT NULL COMMENT '密碼', `passwd_salt` char(6) NOT NULL COMMENT '密碼鹽', `mobile` varchar(15) NOT NULL DEFAULT '0' COMMENT '手機號碼', `role` tinyint(4) NOT NULL DEFAULT '3' COMMENT '用戶角色:0-超級管理員|1-管理員|2-開發&測試&運營|3-普通用戶(只能查看)', `user_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '狀態:0-失效|1-有效|2-刪除', `create_by` smallint(6) NOT NULL COMMENT '建立人ID', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間', `update_by` smallint(6) NOT NULL DEFAULT '0' COMMENT '修改人ID', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間', PRIMARY KEY (`user_id`), KEY `idx_m` (`mobile`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='後臺用戶表'; 複製代碼
而後咱們能夠看到,左邊的 Tables
下多出了 admin_user
表,點開就能夠看到字段信息了:數組
咱們先隨便插入2條數據,方便後面的查詢:
先在項目根目錄建立一個文件夾 config
(與 src
同級),專門放置各類配置。
而後新建一個文件 db.ts
:
// config/db.ts const productConfig = { mysql: { port: '數據庫端口', host: '數據庫地址', user: '用戶名', password: '密碼', database: 'nest_zero_to_one', // 庫名 connectionLimit: 10, // 鏈接限制 }, }; const localConfig = { mysql: { port: '數據庫端口', host: '數據庫地址', user: '用戶名', password: '密碼', database: 'nest_zero_to_one', // 庫名 connectionLimit: 10, // 鏈接限制 }, }; // 本地運行是沒有 process.env.NODE_ENV 的,藉此來區分[開發環境]和[生產環境] const config = process.env.NODE_ENV ? productConfig : localConfig; export default config; 複製代碼
Ps:這個文件是不一樣步到 github 的,須要各位讀者結合實際狀況配置
市面上有不少鏈接數據庫的工具,筆者這裏使用的是 Sequelize
,先安裝依賴包:
$ npm i sequelize sequelize-typescript mysql2 -S
或
$ yarn add sequelize sequelize-typescript mysql2 -S
複製代碼
而後在 src
目錄下建立文件夾 database
,而後再建立 sequelize.ts
:
// src/database/sequelize.ts import { Sequelize } from 'sequelize-typescript'; import db from '../../config/db'; const sequelize = new Sequelize(db.mysql.database, db.mysql.user, db.mysql.password || null, { // 自定義主機; 默認值: localhost host: db.mysql.host, // 數據庫地址 // 自定義端口; 默認值: 3306 port: db.mysql.port, dialect: 'mysql', pool: { max: db.mysql.connectionLimit, // 鏈接池中最大鏈接數量 min: 0, // 鏈接池中最小鏈接數量 acquire: 30000, idle: 10000, // 若是一個線程 10 秒鐘內沒有被使用過的話,那麼就釋放線程 }, timezone: '+08:00', // 東八時區 }); // 測試數據庫連接 sequelize .authenticate() .then(() => { console.log('數據庫鏈接成功'); }) .catch((err: any) => { // 數據庫鏈接失敗時打印輸出 console.error(err); throw err; }); export default sequelize; 複製代碼
好了,接下來咱們來測試一下數據庫的鏈接狀況。
咱們重寫 user.service.ts
的邏輯:
// src/logical/user/user.service.ts import { Injectable } from '@nestjs/common'; import * as Sequelize from 'sequelize'; // 引入 Sequelize 庫 import sequelize from '../../database/sequelize'; // 引入 Sequelize 實例 @Injectable() export class UserService { async findOne(username: string): Promise<any | undefined> { const sql = ` SELECT user_id id, real_name realName, role FROM admin_user WHERE account_name = '${username}' `; // 一段平淡無奇的 SQL 查詢語句 try { const res = await sequelize.query(sql, { type: Sequelize.QueryTypes.SELECT, // 查詢方式 raw: true, // 是否使用數組組裝的方式展現結果 logging: true, // 是否將 SQL 語句打印到控制檯,默認爲 true }); const user = res[0]; // 查出來的結果是一個數組,咱們只取第一個。 if (user) { return { code: 200, // 返回狀態碼,可自定義 data: { user, }, msg: 'Success', }; } else { return { code: 600, msg: '查無此人', }; } } catch (error) { return { code: 503, msg: `Service error: ${error}`, }; } } } 複製代碼
保存文件,就會看到控制檯刷新了(前提是使用 yarn start:dev
啓動的),並打印下列語句:
這說明以前的配置生效了,咱們試着用以前的參數請求一下接口:
返回「查無此人」,說明數據庫沒有叫「Kid」的用戶。
咱們改爲正確的已存在的用戶名再試試:
而後觀察一下控制檯,咱們的查詢語句已經打印出來了,經過 logging: true
,能夠在調試 Bug 的時候,更清晰的查找 SQL 語句的錯誤,不過建議測試穩定後,上線前關閉,否則記錄的日誌會很繁雜:
再對照一下數據庫裏的表,發現查出來的數據和數據庫裏的一致,至此,MySQL 鏈接測試完成,之後就能夠愉快的在 Service 裏面搬磚了。
這篇介紹了 MySQL 的數據準備、Sequelize 的配置、Nest 怎麼經過 Sequelize 鏈接上 MySQL,以及用一條簡單的查詢語句去驗證鏈接狀況。
在這裏,強烈建議使用寫原生 SQL 語句去操做數據庫。
雖然 Sequelize 提供了不少便捷的方法,具體可去 Sequelize v5 官方文檔 瀏覽學習。但筆者經過觀察 logging
打印出來的語句發現,其實多了不少無謂的操做,在高併發的狀況下,太影響性能了。
並且若是不使用原生查詢,那麼就要創建對象映射到數據庫表,而後每次工具更新,還要花時間成本去學習,若是數據庫改了字段,那麼映射關係就會出錯,而後項目就會瘋狂報錯以至宕機(親身經歷)。
而使用原生 SQL,只須要學一種語言就夠了,換個工具,也能用,並且就算改了字段,也只會在請求接口的時候報錯,到時候再針對那個語句修改就行了,並且如今查找替換功能這麼強大,批量修改也不是難事。
最重要的是,若是你是從前端轉後端,或者根本就是0基礎到後端,仍是建議先把 SQL 的基礎打牢,否則連 JOIN
、LEFT JOIN
和 RIGHT JOIN
的區別都分不清(咱們公司就有個三年經驗的後端,亂用 LEFT JOIN
,而後被 DB 主管一頓痛罵。。。真事兒)。
多寫、多分析、多看控制檯報錯、多從性能上考慮,纔是最快入門的途徑。
注意:在寫 UPDATE 更新語句的時候,必定要加上 WHERE 條件,必定要加上 WHERE 條件,必定要加上 WHERE 條件,重要的事情說3遍,血與淚的教訓!!!
下一篇,將介紹如何使用 JWT(Json Web Token)進行單點登陸。
本篇收錄於NestJS 實戰教程,更多文章敬請關注。
`