一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第23天,点击查看活动详情。
前情提要
- 前面讲过如何使用msyql模块封装我们在nodejs中会经常遇到的CURD场景的工具类方法
- mysql模块已经一年多没有更新了,而mysql2模块一直在更新中...
- mysql2相对于mysql模块在性能上有一定程度上得提升。用官方的话就是相比较于mysql模块有更快更优的性能提升。
- mysql2模块在尽可能支持原生api的基础上新增了部分属于自己的东西。
- 也是目前比较推荐使用的模块,使用mysql模块的同学们,赶紧加入转mysql2模块的队列吧。
- 安装方式:npm i mysql2 -S
mysql2连接数据库
- 老样子,先看看怎么实现最基本的即连即用即关的方法。
-
mysql2模块中query的两种方式,
- 一种是mysql模块中的简单模式,开发者自己把相关的值什么的都拼好,组合成完整的sql语句,然后传给封装好的query方法去执行。
- 另外一种是采用占位符的方式,传给query方法的时候第一个参数是sql语句,第二个是一个数组,按照占位符的顺序依次放置值。当然如果只有一个变量的话,那么可以不用写成数组,直接给值也可以。
-
代码示例:
const mysql = require('mysql2'); // 其实相对于这块的配置,跟之前写的一篇关于mysql模块封装的配置都一样(前情提要中的第一行有传送门), // 毕竟升级不代表改天换地,最终都还是要基于mysql的,所以基本配置是不会有非常大的变动的. const con = mysql.createConnection({...}) // 第一种方式详情见前情提要模块的传送门 // 以下是第二种方式: const query = (sql, values) => { return new Promise((resolve, reject) => { con.query(sql, values, function(err, result) => { if (err) reject(err); else resolve(JSON.parse(JSON.stringify(result))); }) }) } module.exports = query; // 具体: query('SELECT * FROM `users` WHERE `id` = ? ', [10]);
-
- 上面的方式与mysql模块提供的其实如出一辙,没有什么特别新颖的地方。而其被称之为比mysql模块性能更优的原因在于其提供了另外一种方法:execute
-
官方给的解释是这个方法如果接收到同一个语句时它不会去执行sql,而是去LRU缓存中去查找。
-
展示封装后的方法:区别只是把query换成execute
... // 此处省略上面已经重复过得操作 const query = (sql, values) => { return new Promise((resolve, reject) => { con.execute(sql, values, function(err, result, fields) => { if (err) reject(err); else resolve(JSON.parse(JSON.stringify(result))); // ?? 对于fieleds,官方的意思是会如果可用的话会返回包含关于结果的额外元数据。 // 没有遇到过这种业务场景,如果有知道的家人们,帮忙在评论区发一下,补充下我的空白,特此感谢。 if (fields) console.log(fields); }) }) } module.exports = query; -
而实际上mysql2已经实现了对promise的支持(但我个人认为上面的方式应该没有过时,有不同意见的欢迎提出来。)。相关如何在项目中实践mysql2中的promise,后续会写一篇专门的文章。这里就不做过多的阐述了。
-
- 使用连接池
-
概念与mysql模块中的是一样的,形式上稍微有一点点的区别
const mysql = require('mysql2'); const con = mysql.createPoool({ host: 'localhost', // ip地址 user: 'root', // 用户名 database: 'test', // 数据库名称 waitForConnections: true, // 是否等待连接 connectionLimit: 10, // 最大连接数 queueLimit: 0 }) const query = (sql, values) => { return new Promie((resolve, reject) => { con.getConnection(function(err, conn) { if (err) reject(err); conn.execute(sql, values, (err, result) => { if (err) reject(err); else resolve(JSON.parse(JSON.stringify(rows))); // 查询完之后释放连接 con.releaseConnection(conn); // 释放连接 }) }) }) } module.exports = query
-
总结
- mysql2中采用了execute的方式,同一条sql语句,不会先去执行代码,而是LRU缓存里找。这种方式本身就接省了一部分时间开销。极力推荐。
- 预防sql注入式攻击
- 针对mysql2模块自带的promise,还有待进一步的研究...