上一篇介紹瞭如何建立項目、路由的訪問以及如何建立模塊,這篇來說講數據庫的鏈接與使用。前端
既然是後端項目,固然要能連上數據庫,不然還不如直接寫靜態頁面。mysql
本教程使用的是 MySQL,有人可能會問爲啥不用 MongoDB。。。呃,由於公司使用 MySQL,我也是結合項目經歷寫的教程,MongoDB 還沒踩過坑,因此就不在這誤人子弟了。git
首先要確保你有數據庫能夠鏈接,若是沒有,能夠在 MySQL 官網下載一個,本地跑起來。安裝教程這裏就不敘述了,「百度一下,你就知道」。github
推薦使用 Navicat Premium 可視化工具來管理數據庫。sql
用 Navicat 鏈接上數據庫後,新建一個庫:typescript
點開咱們剛建立的庫 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)進行單點登陸。
`