前提:已安裝MySql Server
內(nèi)容:使用Node.js的MySQL驅(qū)動(dòng)來(lái)實(shí)現(xiàn)Node.js持久化
安裝
下載mysql依賴:
npm i mysql –S
導(dǎo)入mysql模塊
const mysql = require('mysql')
介紹
Node.js的MySQL驅(qū)動(dòng)由JS編寫,不需要編譯,MIT開(kāi)源。使用方法非常簡(jiǎn)單。
Node.js的mysql驅(qū)動(dòng)地址:
https://github.com/mysqljs/mysql
官方的例子如下:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});
connection.connect();
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});
connection.end();
通過(guò)以上例子,我們知道了使用Node.js的原生MySQL驅(qū)動(dòng)主要通過(guò)以下方法:
- mysql.createConnection(cfg):創(chuàng)建連接對(duì)象,傳入連接配置
連接配置:
連接配置是一個(gè)對(duì)象,包含的項(xiàng)如下:- host: 連接數(shù)據(jù)庫(kù)所在的主機(jī)名. (默認(rèn): localhost)
- port: 連接端口. (默認(rèn): 3306)
- localAddress: 用于TCP連接的IP地址. (可選)
- socketPath: 鏈接到unix域的路徑。在使用host和port時(shí)該參數(shù)會(huì)被忽略.
- user: MySQL用戶的用戶名.
- password: MySQL用戶的密碼.
- database: 鏈接到的數(shù)據(jù)庫(kù)名稱 (可選).
- charset: 連接的字符集. (默認(rèn): 'UTF8_GENERAL_CI'.設(shè)置該值要使用大寫!)
- timezone: 儲(chǔ)存本地時(shí)間的時(shí)區(qū). (默認(rèn): 'local')
- stringifyObjects: 是否序列化對(duì)象. See issue #501. (默認(rèn): 'false')
- insecureAuth: 是否允許舊的身份驗(yàn)證方法連接到數(shù)據(jù)庫(kù)實(shí)例. (默認(rèn): false)
- typeCast: 確定是否講column值轉(zhuǎn)換為本地JavaScript類型列值. (默認(rèn): true)
- queryFormat: 自定義的查詢語(yǔ)句格式化函數(shù).
- supportBigNumbers: 數(shù)據(jù)庫(kù)處理大數(shù)字(長(zhǎng)整型和含小數(shù)),時(shí)應(yīng)該啟用 (默認(rèn): false).
- bigNumberStrings: 啟用 supportBigNumbers和bigNumberStrings 并強(qiáng)制這些數(shù)字以字符串的方式返回(默認(rèn): false).
- dateStrings: 強(qiáng)制日期類型(TIMESTAMP, DATETIME, DATE)以字符串返回,而不是一javascript Date對(duì)象返回. (默認(rèn): false)
- debug: 是否開(kāi)啟調(diào)試. (默認(rèn): false)
- multipleStatements: 是否允許在一個(gè)query中傳遞多個(gè)查詢語(yǔ)句. (Default: false)
- flags: 鏈接標(biāo)志.
你也可以直接使用一個(gè)字符串來(lái)連接數(shù)據(jù)庫(kù)
var connection = mysql.createConnection('mysql://user:pass@host/db?debug=true&charset=BIG5_CHINESE_CI&timezone=-0700');
- connection.connect() : 連接數(shù)據(jù)庫(kù)
- connection.query(sql,(err,result)=>{}):查詢語(yǔ)句,此驅(qū)動(dòng)所有sql語(yǔ)句都通過(guò)query語(yǔ)句執(zhí)行
- connection.end():關(guān)閉連接,在關(guān)閉連接時(shí)需要確認(rèn)所有的query語(yǔ)句都執(zhí)行完畢。需要放在順序執(zhí)行的最后。如果query出錯(cuò),仍然會(huì)終止連接,錯(cuò)誤會(huì)傳遞到回調(diào)函數(shù)中處理。還要一個(gè)connection.destroy()方法的作用也是結(jié)束數(shù)據(jù)庫(kù)連接,與end方法不同的是,destroy方法會(huì)立即終止連接,即使還有query方法還沒(méi)有完成,也不會(huì)觸發(fā)回調(diào)函數(shù)。
每個(gè)使用在連接對(duì)象上的方法都是同步的,順序執(zhí)行的。意味著此驅(qū)動(dòng)沒(méi)有提供異步的想promise的方法。
實(shí)例步驟1、連接數(shù)據(jù)庫(kù)
新建mysql.js文件,安裝并引入mysql模塊,設(shè)置用戶密碼等連接數(shù)據(jù)庫(kù):
const mysql = require('mysql')
//連接配置
const cfg = {
host:'localhost',
user:'root',//默認(rèn)root用戶
password:'admin',
database:'test',
}
//創(chuàng)建連接對(duì)象
const conn = mysql.createConnection(cfg);
//連接數(shù)據(jù)庫(kù)
conn.connect(err =>{
if(err){
throw err
}
console.log("連接成功")
})
運(yùn)行文件:
nodemon .\mysql
nodemon可自動(dòng)監(jiān)測(cè)node.js文件變化

運(yùn)行結(jié)果
也可以通過(guò)查詢語(yǔ)句來(lái)連接數(shù)據(jù)庫(kù)
const mysql = require('mysql')
//連接配置
const cfg = {
host:'localhost',
user:'root',//默認(rèn)root用戶
password:'admin',
database:'test',
}
//創(chuàng)建連接對(duì)象
const conn = mysql.createConnection(cfg);
//連接并執(zhí)行sql
conn.query('SELECT 1', function (error, results, fields) {
if (error) throw error;
console.log("連接成功")
});
執(zhí)行結(jié)果:

執(zhí)行結(jié)果
實(shí)例步驟2、使用連接池
mysql驅(qū)動(dòng)提供了連接池來(lái)提高查詢和操作效率。
實(shí)例如下:
var pool = mysql.createPool({
connectionLimit : 10,
host:'localhost',
user:'root',//默認(rèn)root用戶
password:'admin',
database:'test',
});
pool.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log("連接成功")
console.log('The solution is: ', results[0].solution);
});
執(zhí)行結(jié)果:

執(zhí)行結(jié)果
通過(guò)以上實(shí)例,使用連接池的方法如下:
- mysql.createPool(cfg):傳入連接配置,這個(gè)方法是
pool.getConnection() -> connection.query() -> connection.release()的一個(gè)簡(jiǎn)單版本,connection.release()釋放鏈接到連接池。如果需要關(guān)閉連接并且刪除,需要使用connection.destroy()
pool除了接受和connection相同的參數(shù)外,還接受幾個(gè)擴(kuò)展的參數(shù)- createConnection: 用于創(chuàng)建鏈接的函數(shù). (Default: mysql.createConnection)
- waitForConnections: 決定當(dāng)沒(méi)有連接池或者鏈接數(shù)打到最大值時(shí)pool的行為. 為true時(shí)鏈接會(huì)被放入隊(duì)列中在可用是調(diào)用,為false時(shí)會(huì)立即返回error. (Default: true)
- connectionLimit: 最大連接數(shù). (Default: 10)
- queueLimit: 連接池中連接請(qǐng)求的烈的最大長(zhǎng)度,超過(guò)這個(gè)長(zhǎng)度就會(huì)報(bào)錯(cuò),值為0時(shí)沒(méi)有限制. (Default: 0)
實(shí)例步驟3、使用query
通過(guò)上述我們知道query方法是mysql驅(qū)動(dòng)進(jìn)行sql語(yǔ)句執(zhí)行的唯一方法,創(chuàng)建幾個(gè)sql語(yǔ)句并執(zhí)行如下:
const mysql = require('mysql')
//連接配置
const cfg = {
host:'localhost',
user:'root',//默認(rèn)root用戶
password:'admin',
database:'test',
}
//創(chuàng)建連接對(duì)象
const conn = mysql.createConnection(cfg);
//sql語(yǔ)句
const CREATE_SQL = `CREATE TABLE IF NOT EXISTS test (
id INT NOT NULL AUTO_INCREMENT,
message VARCHAR(45) NULL,
PRIMARY KEY (id))`;
const INSERT_SQL = `INSERT INTO test(message) VALUES(?)`;
const SELECT_SQL = `SELECT * FROM test`;
//連接數(shù)據(jù)庫(kù)
conn.connect(err =>{
if(err){
throw err
}
console.log("連接成功")
//創(chuàng)建表
conn.query(CREATE_SQL,(err) =>{
//插入數(shù)據(jù)
//格式化sql語(yǔ)句并輸出
const sql = mysql.format(INSERT_SQL,'hello');
console.log(sql);
conn.query(INSERT_SQL,'hello',(err,result)=>{
console.log(result);
conn.query(SELECT_SQL,(err,results)=>{
console.log(results);
//不使用連接池時(shí)需要關(guān)閉
conn.end();
})
})
})
})
運(yùn)行如下:

執(zhí)行結(jié)果
我們知道m(xù)ysql驅(qū)動(dòng)是不提供promise方法的,如果我們想使用,我們可以自己封裝一個(gè)query方法:
//封裝
function query(conn,sql,param=null){
return new Promise((resolve,reject)=>{
conn.query(sql,param,(err,results)=>{
if(err){
reject(err)
}else{
resolve(results)
}
})
})
}
使用方法如下:
query(conn,SELECT_SQL).then(results=>{
console.log(results)
}).catch(err=>{
console.log(err)
})