基于原生sql在node中使用mysql2模块进行sql封装【二】

1,739 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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,还有待进一步的研究...