node+express+grunt+mysql操作資料庫案例分析
簡單嘮兩句、
在以前的node操作資料庫,都是選擇mongodb這型別的非關係型資料庫,進行資料儲存操作。而這次業務涉及到mysql,所以來簡單瞭解下node環境下,是如何操作mesql資料庫增刪改查的?
一、安裝
1. 開發依賴
yarn init yarn add mysql yarn add express yarn global add add json-server # 本地服務工具 yarn global add add nodemon / 或者 yarn add --dev grunt grunt-contrib-watch grunt-execute # 自動化工具
2. 資料庫工具:Navicat for MySQL
破解版下載地址:https://pan.baidu.com/s/1u8GGJ5AFFvAJKbXij4NyMA 提取碼: vhzc
二、開發測試思路
採用json-server啟動本地服務,預設啟動public目錄下index.html檔案,在index.html檔案中fetch請求express啟動的服務,根據請求的對應路由操作mysql資料庫
D:\me\npm\node-mysql>json-server db.json --port 3006 \{^_^}/ hi! Loading db.json Done Resources http://localhost:3006/posts http://localhost:3006/comments http://localhost:3006/profile Home http://localhost:3006 Type s + enter at any time to create a snapshot of the database
三、開發過程
1. 啟動mysql服務,新建資料庫,插入一些測試資料
(1)執行sql指令碼:
CREATE TABLE employees ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(50), location varchar(50), PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ; INSERT INTO employees (id, name, location) VALUES (1, 'Jasmine', 'Australia'), (2, 'Jay', 'India'), (3, 'Jim', 'Germany'), (4, 'Lesley', 'Scotland');
(2)或者手動插入
2. 新建/server.js檔案、public/index.html檔案
(1)server.js中開啟服務,配置允許跨域請求,連線mysql資料庫
// server.js
const mysql = require('mysql');
const app = require('express')();
//allow cross origin
app.all('*', function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
//Access-Control-Allow-Headers ,可根據瀏覽器的F12檢視,把對應的貼上在這裡就行
res.header('Access-Control-Allow-Headers', 'Content-Type');
res.header('Access-Control-Allow-Methods', '*');
res.header('Content-Type', 'application/json;charset=utf-8');
next();
});
// First you need to create a connection to the db
const con = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'root',
database: 'node'
});
con.connect((err) => {
if(err){
console.log('Error connecting to Db');
return;
}
console.log('Connection established');
});
con.end((err) => { //注:在end之後就不能操作資料庫了! });
(2) 啟動node服務
C:\web\npm\node-mysql>node server.js
Connection established
(3) 根據需求或者個人喜好安裝nodemon/grunt自動編譯工具,如下是grunt的安裝
2-3-1. 安裝
C:\web\npm\node-mysql>cnpm install -g grunt grunt-contrib-watch grunt-execute
2-3-2. 檢視版本
C:\web\npm\node-mysql>grunt --version
grunt-cli v1.2.0
grunt v1.0.3
2-3-3. 新建一個Gruntfile.js檔案
module.exports = (grunt) => {
grunt.initConfig({
execute: {
target: {
src: ['./server.js']
}
},
watch: {
scripts: {
files: ['./server.js'],
tasks: ['execute'],
},
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-execute');
};
2-3-4. 執行監聽
C:\web\npm\node-mysql>grunt watch
Running "watch" task
Waiting...
>> File "server.js" changed.
Running "execute:target" (execute) task
-> executing C:\web\npm\node-mysql\server.js
Connected !
-> completed C:\web\npm\node-mysql\server.js (254ms)
>> 1 file and 0 calls executed (270ms)
Done.
Completed in 0.835s at Tue Oct 23 2018 21:44:08 GMT+0800 (中國標準時間) - Waiting...
(4)index.html檔案中發出fetch請求服務,如下
fetch('http://localhost:3000/delete').then(res=>res.json()).then((res)=>{
document.querySelector('#box').innerHTML += JSON.stringify(res);
});
2.查詢所有資料
// 查詢所有資訊
app.get('/getAll', function(req, res){
connection.query('SELECT * FROM employees', (err,rows) => {
res.send(rows);
});
});
3. 插入資料資訊
app.get('/set', function(req, res){
console.log('123');
const employ = {name: '小虎的家鄉', location: '九寨溝'};
connection.query('INSERT INTO employees SET ?',employ, (err,doc) => {
res.send(doc);
//{"fieldCount":0,"affectedRows":1,"insertId":5,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0}
});
});
4. 更新資料
app.get('/update', function(req, res){
const employ = ['大明王朝的芹菜',1];
connection.query('update employees SET location = ? where ID = ? ',employ, (err,doc) => {
res.send(doc);
//{"fieldCount":0,"affectedRows":1,"insertId":0,"serverStatus":2,"warningCount":0,"message":"(Rows matched: 1 Changed: 1 Warnings: 0","protocol41":true,"changedRows":1}
});
});
5. 刪除資訊
app.get('/delete', function(req, res){
connection.query('DELETE FROM employees WHERE id = ?',4, (err,doc) => {
res.send(doc);
//{"fieldCount":0,"affectedRows":1,"insertId":0,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0}
});
});
四、使用儲存過程查詢資料庫
1. 首先需要在navicat中執行如下查詢結構:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_getall`()
BEGIN
SELECT id, name, location FROM employees;
END
2. 然後在server.js中執行查詢服務
connection.query('CALL sp_getall()',function(err,rows){
if(err) throw err;
console.log('Data received form Db: \n');
console.log(rows);
});
3. 列印如下:
Data received form Db:
[ [ RowDataPacket { id: 1, name: 'Jasmine', location: 'Australia' },
RowDataPacket { id: 2, name: 'Jay', location: 'India' },
RowDataPacket { id: 3, name: 'Jim', location: 'Germany' },
RowDataPacket { id: 4, name: 'Lesley', location: 'Scotland' },
RowDataPacket { id: 5, name: null, location: null } ],
OkPacket {
fieldCount: 0,
affectedRows: 0,
insertId: 0,
serverStatus: 34,
warningCount: 0,
message: '',
protocol41: true,
changedRows: 0 } ]
五、使用儲存過程傳遞引數查詢
1. 執行sql語句
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_get_employee_detail`(
in employee_id int
)
BEGIN
SELECT name, location FROM employees where id = employee_id;
END
2. server.js中執行查詢
// 使用儲存過程查詢id為1的資料
connection.query('CALL sp_get_employee_detail(2)',function(err,rows){
if(err) throw err;
console.log('Data received form Db: \n');
console.log(rows);
});
3. 列印如下:
Data received form Db:
[ [ RowDataPacket { name: 'Jasmine', location: 'Australia' } ],
OkPacket {
fieldCount: 0,
affectedRows: 0,
insertId: 0,
serverStatus: 2,
warningCount: 0,
message: '',
protocol41: true,
changedRows: 0 } ]
五、使用儲存過程插入資料操作
1. 執行sql語句
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_insert_employee`(
out employee_id int,
in employee_name varchar(25),
in employee_location varchar(25)
)
BEGIN
insert into employees(name, location)
values(employee_name, employee_location);
set employee_id = LAST_INSERT_ID();
END
2. `query查詢` (前置條件:需要把connect的連線引數物件中增加欄位 multipleStatements: true )
connection.query( "SET @employee_id = 0; CALL sp_insert_employee(@employee_id, 'tiger', 'forest'); SELECT @employee_id",function(err,rows){
if(err) throw err;
console.log('Data received form Db: \n');
console.log(rows);
});
3. 列印如下:
Data received form Db:
[ OkPacket {
fieldCount: 0,
affectedRows: 0,
insertId: 0,
serverStatus: 10,
warningCount: 0,
message: '',
protocol41: true,
changedRows: 0 },
OkPacket {
fieldCount: 0,
affectedRows: 1,
insertId: 0,
serverStatus: 10,
warningCount: 0,
message: '',
protocol41: true,
changedRows: 0 },
[ RowDataPacket { '@employee_id': 11 } ] ]
六、安全轉義引數
const userLandVariable = 4;
connection.query(
`SELECT * FROM employees WHERE id = ${mysql.escape(userLandVariable)}`,
function(err, rows){
console.log(rows);
}
);
// [ RowDataPacket { id: 4, name: 'Lesley', location: 'Scotland' } ]
七、結論
無論什麼時候,不管遇到什麼情況,我絕不允許自己有一點點灰心喪氣。—— 愛迪生