使用 NodeJS 开发,必不可少的肯定会涉及到数据存储,此篇就以 MySQL 为例来看数据库存取业务的开发。在使用 MySQL 之前,需要先安装 MySQL 驱动。
1
| npm install mysql --save
|
连接数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var mysql = require('mysql'); var conn = mysql.createConnection({ host: '127.0.0.1', user: 'root', password: '111111', database: 'mydb', port: 3306 }); conn.connect(); conn.query('select * from User', function(err, result) { console.log(result); }); conn.end();
|
使用 conn.query 方法查询数据,query 方法同样也可以进行 新增、删除、更新 操作,从回调函数的第二个参数中可以获取到对应的执行结果。
增删改查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| conn.query('insert into user (username,password) ...', function(err, result) { if (err) throw err; console.log(result); }) conn.query('delete from user where username="wupeigui"', function(err, result) { if (err) throw err; console.log(result); }) conn.query('update user set id="1" where username="huxiaona"',function(err,result){ if (err) {throw err}; console.log("修改数据成功"); })
|
删除和更新,可以通过 result.affectedRows 来获取受影响的行数;
数据库连接池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var connParams = { host: '127.0.0.1', user: 'root', password: '111111', database: 'mydb', port: 3306 }; var pool = mysql.createPool(connParams); pool.query('select * from User',function(err, rs, fields){ console.log(rs); }); pool.getConnection(function(err, conn){ conn.query('select * from User', function(err, rs) { console.log(rs); conn.release(); }); });
|
连接池配置选项
createConnection 方法还可以传入一些其它选项参数。
- waitForConnections: 当连接池没有连接或超出最大限制时,设置为true且会把连接放入队列,设置为false会返回error
- connectionLimit: 连接数限制,默认:10
- queueLimit: 最大连接请求队列限制,设置为0表示不限制,默认:0
连接释放
调用connection.release()方法,会把连接放回连接池,等待其它使用者使用!
连接错误处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| var conn = 0; function handleError() { var connParams = { host: '127.0.0.1', user: 'root', password: '1111110', database: 'mydb', port: 3306 }; conn = mysql.createConnection(connParams); conn.connect(function(err) { if(err){ console.log(err); } }); conn.on('error', function(err) { console.log('db error'); if (err.code === 'PROTOCOL_CONNECTION_LOST') { handleError(); } else { throw err; } }); } handleError();
|
上面的代码可以处理 登录密码错误,数据库宕机,连接超时。
1
| PROTOCOL_CONNECTION_LOST
|
使用 root 账户修改 MySQL 的 wait_timeout 参数,设为10秒;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| ~ mysql -u root -p mysql> show variables like 'wait_timeout'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | wait_timeout | 28800 | +---------------+-------+ 1 row in set (0.00 sec) mysql> set global wait_timeout=10; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'wait_timeout'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | wait_timeout | 10 | +---------------+-------+ 1 row in set (0.00 sec)
|
添加测试代码
1 2 3 4 5 6 7 8 9
| function query(){ console.log(new Date()); var sql = "show variables like 'wait_timeout'"; conn.query(sql, function (err, res) { console.log(res); }); } setInterval(query, 15*1000);
|
MySQL 连接池超时测试
1 2 3 4 5 6 7 8 9 10 11 12 13
| var selectSQL ="show variables like 'wait_timeout'"; pool.getConnection(function (err, conn) { if (err) console.log("POOL ==> " + err); function query(){ conn.query(selectSQL, function (err, res) { console.log(new Date()); console.log(res); conn.release(); }); } setInterval(query, 12 * 1000); });
|
事务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| connection.beginTransaction(function(err) { if (err) { throw err; } connection.query('INSERT INTO posts SET title=?', title, function(err, result) { if (err) { connection.rollback(function() { throw err; }); } var log = 'Post ' + result.insertId + ' added'; connection.query('INSERT INTO log SET data=?', log, function(err, result) { if (err) { connection.rollback(function() { throw err; }); } connection.commit(function(err) { if (err) { connection.rollback(function() { throw err; }); } console.log('success!'); }); }); }); });
|
转义
字符串转义
在使用客户端输入的值来组装查询语句时,需要对这些值进行正确的转义,以避免遭受 SQL注入 攻击。可以使用 escape() 方法来对这些值进行转义:
1 2 3 4 5
| var sql = 'select * from User where id = ' + conn.escape("27 or id = 28"); console.log(sql); conn.query(sql, function(err, resulst){ console.log(resulst); });
|
还可以在SQL语句中将要转义的值用问号 ? 来代替,再在调用 query() 方法时传入这些待转义的值:
1 2 3
| conn.query('select * from User where id=? or id=?', [27, 28], function(err, rs){ console.log(rs); });
|
标识符转义
与字符串值的转义类似,标识符的转义可以使用 escapeId() 方法来实现:
1 2 3 4 5 6 7
| var sorter = 'date'; var query = 'SELECT * FROM posts ORDER BY ' + mysql.escapeId(sorter); console.log(query); var sorter = 'date'; var query = 'SELECT * FROM posts ORDER BY ' + mysql.escapeId('posts.' + sorter); console.log(query);
|
也可以在 SQL 语句中使用两个问号 ?? 来表示要转义的标识符:
1 2 3 4 5
| var userId = 1; var columns = ['username', 'email']; var query = connection.query('SELECT ?? FROM ?? WHERE id = ?', [columns, 'users', userId], function(err, results) {}); console.log(query.sql);
|